【问题标题】:Mapping JSON object to observable for use with ngFor Angular将 JSON 对象映射到可观察对象以与 ngFor Angular 一起使用
【发布时间】:2019-02-26 18:29:13
【问题描述】:

我正在尝试将 JSON 对象映射到我在我的 Angular 应用程序中配置的可观察接口,我希望一旦我映射了它,我可以将它用作循环通过 ngFor 的输入。

不幸的是,我不相信我正在正确配置我的服务,或者可能是服务调用。

我将 json 对象作为单个对象返回,但 ngFor 没有正确循环返回的结果,任何帮助指出我可能忽略的内容将不胜感激。

// 我正在尝试访问的接口

export interface IProduct {
   name: string;
   description: string;
   price: number;
   category: string;
   image: string;
}

// 我正在尝试调用的服务

private productList = new BehaviorSubject<IProduct[]|null>(null);
productListChanges$ = this.productList.asObservable();
constructor(private http: HttpClient) { }

getProds(): Observable<IProduct[]> {
     this.productList.next(null);
     return this.http.get<IProduct[]> 
                      ('http://localhost:4200/assets/data/products.json')
     .pipe(
        tap(data => this.productList.next(data)),
     );
 }

// 调用服务

productsList: IProduct[] = [];

this.productService.getProds().subscribe((response: any) => {
  this.productsList = response.products[0] as IProduct[];
  console.log(this.productsList);
});

// 尝试将 ngFor 用于获取的对象

<app-product *ngFor="let product of productsList" [prod]="product" ></app-product>

// 来自服务调用的控制台日志输出以下内容

logOutput from service call

【问题讨论】:

    标签: angular components angular-services ngfor


    【解决方案1】:

    在使用 Observables 循环时尝试使用异步。

    <app-product *ngFor="let product of productsList | async" [prod]="product" ></app-product>
    

    【讨论】:

    • 尝试实现异步,但唯一的区别是控制台日志输出一个“对象”并且 ngFor 仍然无法正常运行
    【解决方案2】:

    我看到您正在使用 HTTP 来提供 JSON 数据,这些数据很容易作为来自资产文件夹中存在的静态文件的数据提供。我会避免使用 HTTP 调用来提供这些服务。我已经重构了您的代码以提供静态数据,并且还支持使用相同的服务方法进行远程数据查询。它还应该在单元测试期间有所帮助,因为异步测试是一场噩梦。

    // Changed the Interface to a class
    export class Product {
       name: string;
       description: string;
       price: number;
       category: string;
       image: string;
    }
    
    // Create a sample-data.ts file
    export const ProductListData: Array<Product> = [
        {
           name: 'ProductName',
           description: 'Description',
           price: '9.99', // Maybe should be a number type and not string
           category: 'Test Category',
           image: 'your url for testing'
        }
    ]
    
    // In service... 
    import { of } from 'rxjs';
    import { ProductListData } from './sample-data';
    useSampleData = false;
    
    getProducts(): Observable<Array<Product>> {
        if (useSampleData) {
            // Use this is your want to serve static JSON
            return of(ProductListData); // of() turns your readily avialable object into an obeservable promise
        } else {
        // Get from actual HTTP as async
            return this.http.get<Array<Product>>('http://localhost:4200/api/your-endpoint-url');
        }
     }
     
     
    // In you Component...
    public productList: Array<Product> = [];
    
    this.productService.getProducts().subscribe(
        productList => {
          this.productsList = productList;
        },
        err => {
            console.log('Error: ', err);
        }
    );

    您的模板不需要更改。

    【讨论】:

    • 我尝试进行所有指示的更改,但似乎 ngFor 仍未正确构建...不确定我在这里缺少什么...就像 productsList 是一个数组ngFor 没有正确读取的对象?
    • 你能分享任何新的错误吗?您能否在对您的服务的组件调用中添加一个 console.log,以便我们确认对象已到达?
    【解决方案3】:

    正如您的控制台输出所示,productsList 是一个对象,但 ngFor 需要一个数组。

    如果您可以更改数据,则应该可以轻松地将其更改为数组 ([...]) 而不是对象 ({...})。

    否则,您有多种选择可以将代码中的结构转换为数组。例如,当使用Object.values() 时,您可以将当前结构转换为数组。或者,您也可以使用自 Angular 6.1 起可用的 KeyValuePipe。也在这里回答https://stackoverflow.com/a/51491848/9999800

    【讨论】:

    • 这个答案实际上为我做了,这样的疏忽,将 products.json 本身调整为 [{},{},{}] 而不是 { 1: {}, 2:{} , 3:{} }。非常感谢您的意见
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 2018-07-24
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多