【问题标题】:Angular8 - can't iterate over objectAngular8 - 无法迭代对象
【发布时间】:2019-09-02 19:38:46
【问题描述】:

我使用的是 Angular8,下面的代码如下。

问题:

  1. 为什么在组件中 Observable 只有一项(应该有四项)。
  2. 在 html 中,为什么我不能遍历对象?我以为它是一个数组。

服务:

private listProductsJSON: any;
private listProducts$: BehaviorSubject<Product[]>;

public getItems(url: string): Observable<Product[]> {
  this.listProducts$ = <BehaviorSubject<Product[]>> new BehaviorSubject({});
  this.listProductsJSON = require('/Users/richardmarais/Development/examples/angular-menu-routes/menu-routes-app/src/app/model/products.json');  // gets some hard coded json with 4 rows
  Object.keys(this.listProductsJSON.products).map(key => {
    //console.log(this.listProductsJSON.products[key]); // logs 4 rows
    this.listProducts$.next(this.listProductsJSON.products[key]);
  });

  return this.listProducts$.asObservable();
}

组件:

private productsData: Product[];

ngOnInit() {
    this._productService.getItems(this.dataService.serviceData.URL).subscribe((products: Product[]) => {
        console.log(products);  // only logs 1 row        
        this.productsData = products;
    });
}

html:

    <ul>
      <div *ngFor="let product of productsData">
        <li>{{ product }}</li>
      </div>
    </ul>

控制台日志:(应该是四项,但只有一项)

{status: "validated", name: "lions", description: "", id: "yXfhYcDpzYmyWGYptNme", order: 4}

错误:

ProductsComponent.html:5 ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'lions'. NgFor only supports binding to Iterables such as Arrays.
    at NgForOf.ngDoCheck (common.js:4841)
    at checkAndUpdateDirectiveInline (core.js:31912)
    at checkAndUpdateNodeInline (core.js:44366)
    at checkAndUpdateNode (core.js:44305)
    at debugCheckAndUpdateNode (core.js:45327)
    at debugCheckDirectivesFn (core.js:45270)
    at Object.eval [as updateDirectives] (ProductsComponent.html:5)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:45258)
    at checkAndUpdateView (core.js:44270)
    at callViewAction (core.js:44636)
View_ProductsComponent_1 @ ProductsComponent.html:5
logError @ core.js:45545
handleError @ core.js:6066
(anonymous) @ core.js:41057
invoke @ zone-evergreen.js:359
run @ zone-evergreen.js:124
runOutsideAngular @ core.js:39571
tick @ core.js:41054
(anonymous) @ core.js:40892
invoke @ zone-evergreen.js:359
onInvoke @ core.js:39698
invoke @ zone-evergreen.js:358
run @ zone-evergreen.js:124
run @ core.js:39510
next @ core.js:40889
schedulerFn @ core.js:35335
__tryOrUnsub @ Subscriber.js:185
next @ Subscriber.js:124
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:35297
checkStable @ core.js:39641
onHasTask @ core.js:39718
hasTask @ zone-evergreen.js:411
_updateTaskCount @ zone-evergreen.js:431
_updateTaskCount @ zone-evergreen.js:264
runTask @ zone-evergreen.js:185
drainMicroTaskQueue @ zone-evergreen.js:559
invokeTask @ zone-evergreen.js:469
invokeTask @ zone-evergreen.js:1603
globalZoneAwareCallback @ zone-evergreen.js:1629
Show 2 more frames
ProductsComponent.html:5 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 5, nodeDef: {…}, elDef: {…}, elView: {…}}

product.ts

export class Product {
    status:      string;
    name:        string;
    description: string;
    id:          string;
    order:       number;
 }

products.json

{
    "products": {
        "drivers": {
            "status": "validated",
            "name": "drivers",
            "description": "",
            "id": "5rI6n3O2T2z3uKLqbEGj",
            "order": 1
        },
        "zombies": {
            "status": "validated",
            "name": "zombies",
            "description": "active",
            "id": "e6T8tOrbUQH1qyo2ECfj",
            "order": 2
        },
        "passengers": {
            "status": "validated",
            "name": "passengers",
            "description": "",
            "id": "tP4SkWIYRubHN6mCZRA5",
            "order": 3
        },
        "lions": {
            "status": "validated",
            "name": "lions",
            "description": "",
            "id": "yXfhYcDpzYmyWGYptNme",
            "order": 4
        }
    }
}

【问题讨论】:

  • array =/= 对象,检查一下,如何迭代对象属性stackoverflow.com/a/16735184/2796268
  • @B.J.互诫协会谢谢你的信息。据我所知,它提到了hasOwnProperty 的使用。但我不确定这对我有什么帮助?
  • @Richard hasOwnProperty if 用于检查对象是否确实具有属性,但检查原始问题和其他答案

标签: javascript angular observable angular8 behaviorsubject


【解决方案1】:

您应该使用 keyvalue 管道来迭代对象。

例如

HTML

 <ul>
  <div *ngFor="let product of productsData | keyvalue">
    <li>{{ product.value.status }}</li>
  </div>
</ul>

【讨论】:

    【解决方案2】:

    这是你的 JSON:

    {
        "products": {
            "drivers": {
            }
            ... (3 more objects)
         }
    }
    

    正如您在此处看到的,您已经创建了一个值为“products”的对象。如果您要将它放入一个变量中,您可以通过这种方式访问​​它,object.products。 “产品”对象有 4 个属性,drivers 是其中之一 (object.products.drivers)。您期待一个带有 4 个对象的 array

    当您尝试在此处将 json 转换为 typescript 对象时:(products: Product[]) 它会默默地(不确定是否有日志记录)找不到数组,而是将“产品”对象放入数组中。

    要解决这个问题,您需要修复JSON ->

    {
        "products": [ <- array of objects, not an object with properties
            "drivers": {
            }
         ]
    }
    

    为什么会这样?

    this.productsData = Object.values(products).sort((a,b)=>b.order-a.order);
    

    Object.values(),从您提供给它的“产品”对象中获取所有值,并将其放入可迭代数组中。

    【讨论】:

    • 感谢您的反馈。 Object.values(products).sort((a,b)=&gt;b.order-a.order) 不起作用,它只是将其拆分为包含单个产品项的数组。
    • 很遗憾,我无法更改 JSON,因为这是从我无法控制的服务器返回的内容。
    【解决方案3】:

    products 不是数组,JSON 是嵌套对象

    您还应该使用接口而不是export class Product

       export interface Drivers {
            status: string;
            name: string;
            description: string;
            id: string;
            order: number;
        }
    
        export interface Zombies {
            status: string;
            name: string;
            description: string;
            id: string;
            order: number;
        }
    
        export interface Passengers {
            status: string;
            name: string;
            description: string;
            id: string;
            order: number;
        }
    
        export interface Lions {
            status: string;
            name: string;
            description: string;
            id: string;
            order: number;
        }
    
        export interface Products {
            drivers: Drivers;
            zombies: Zombies;
            passengers: Passengers;
            lions: Lions;
        }
    
        export interface ProductRootObject {
            products: Products;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 2020-01-03
      • 1970-01-01
      • 2014-11-10
      • 1970-01-01
      • 2016-05-07
      • 2017-02-23
      • 2014-01-01
      相关资源
      最近更新 更多