web-dev-qa-db-ja.com

タイプ 'Observable <any>'は、タイプ '[]'に割り当てられません

私はAngular2/TypeScriptがかなり新しいので、バカな間違いをしているのなら、すみません。私がやろうとしているのは、Selectドロップダウンから、JSON配列を返すサービスを使用してデータを入力しています。

ここに私のコードがあります:

product-maintenance.component.ts

import { Component, OnInit} from '@angular/core';
import { ProductMaintenanceService } from '../../_services/product-maintenance.service';
import { ModuleConst } from '../../../data/const';
import { Product } from './product-types';
import { Products } from './products';

@Component({
  selector: 'app-product-maintenance',
  templateUrl: './product-maintenance.component.html',
  styleUrls: ['./product-maintenance.component.css']
})

export class ProductMaintenanceComponent implements OnInit {
 selectedProduct: Product = new Product(0, 'Insurance');
 products: Product[];
 productList: Products[];

 constructor( private productService: ProductMaintenanceService ) {

 }

    ngOnInit() {
      // Dropdown list
      this.products = this.productService.getProductTypeList();
    }
    // Populate data using onSelect method
    onSelect(typeid) {
      this.productList = this.productService.getProducts()
        .filter((item)=>item.ptypeid == typeid);
    }
}

product-type.ts(ドロップダウンリストの設定に使用):

export class Product {
  constructor(
    public ptypeid: number,
    public name: string
  ) { }
}

products.ts(サービスからデータを取り込むために使用):

export class Products {
  constructor(
      public id: number,
      public ptypeid: number,
      public name: string,
      public currency: string,
      public state: string,
      public riskRating: number,
      public clientSegment: string,
      public aiStatus: string,
      public premiumType: string,
      public tenure: number
  ) { }
}

product-maintenance.service.ts

import { Injectable, Inject } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';
import { APP_CONFIG, IAppConfig } from '../app.config';
import { Products } from './products';
import { Product } from './product-types';

@Injectable()
export class ProductMaintenanceService {
    result: Array<Object>;
    constructor(
        @Inject(APP_CONFIG) private config: IAppConfig,
        private http: Http
      ) { }

    private productURL = 'data/productList.json';

    // Get product list
    getProducts() : Observable<any> {
     // ...using get request
     return this.http.get(this.productURL)
        // ...and calling .json() on the response to return data
        .map((response: Response) => {
          console.log(response);
          return response.json();
        });
     }


     getProductTypeList() {
       return [
         new Product(1, 'Unit Trust'),
         new Product(2, 'Insurance'),
         new Product(3, 'Structured Deposit'),
         new Product(4, 'Bonds'),
         new Product(5, 'DCI'),
         new Product(6, 'SP')
       ];
     }
}

product-maintenance.component.html

<table>
<tr *ngFor="let item of productList">
                <td>{{ item.id }}</td>
                <td>{{ item.name }}</td>
                <td>{{ item.currency }}</td>
                <td>{{ item.state }}</td>
                <td>{{ item.riskRating }}</td>
                <td>{{ item.clientSegment }}</td>
                <td>{{ item.aiStatus }}</td>
                <td>{{ item.premiumType }}</td>
                <td>{{ item.tenure }}</td>
            </tr>
</table>

productList.json

[
      {
        "ptypeid": 1,
        "id": 1,
        "name": "Unit Trust 1",
        "currency": "SGD",
        "state": "Active",
        "riskRating": 1,
        "clientSegment": "Retail/Premier",
        "aiStatus": "No",
        "premiumType": "Regular Premium",
        "tenure": 5
      },
      {
        "ptypeid": 2,
        "id": 2,
        "name": "Unit Trust 2",
        "currency": "SGD",
        "state": "Active",
        "riskRating": 3,
        "clientSegment": "Retail/Premier",
        "aiStatus": "No",
        "premiumType": "Single/Lumpsum Premium",
        "tenure": 10
      }
]

getProducts()getProductTypeList()として定義すると、ビューのデータが完全に読み込まれます(ドロップダウンから[ユニットの信頼]を選択すると、関連データが読み込まれます)。しかし、代わりにapi urlとして使用すると、以下のエラーが表示されます:

Type 'Observable<any>' is not assignable to type 'Products[]'. Property 'length' is missing in type 'Observable<any>'

このエラーを解決する方法がわかりません。誰でもこれで私を助けてください。前もって感謝します。

14
tutorialfeed

productListProduct[]ではなくObservable<any>である必要があります。したがって、productList subscribeメソッドからgetProducts値を割り当てます。ここで、Productの配列を取得します

onSelect(typeid) {
  this.productService.getProducts()
    .filter((item)=>item.ptypeid == typeid)
    .subscribe((products) => {
       this.productList = products;
    });
}
7
Pankaj Parkar

メソッドをgetProductsメソッドに変更します

getProducts() : Observable<any> {
     // ...using get request
     let response = this.http.get(this.productURL)
        // ...and calling .json() on the response to return data
        .map((response: Response) => response.json());
    return response;
 }
4
Ali Baig

いくつかの問題があります。最初に、get-requestに相対URLを使用していることに気付きました。それはうまくいきません。正しいURLが必要です。つまり、APIがlocalhostにある場合でも、http://..で始まるものは完全なURLを提供する必要があります。

次に、getリクエストは問題ありませんが、コンポーネントでの呼び出しは次のようになります。

this.productService.getProducts()
  .subscribe(data => {
   this.productList = data})

リクエストでマップを実行しているので、それもサブスクライブする必要があります。そうしないと、結果が得られません!

また、言及する価値があるのは、これは非同期操作であるため、データが到着する前にビューがレンダリングされた場合にアプリがエラーをスローしないように、テーブルにngIfを含めることができます。この:

<table *ngIf="productList">

これで事態は一掃されるはずです!

または、サブスクライブしたくない場合は、以前と同じように実行できます。

this.products = this.productService.getProductTypeList();

ただし、ビューでasyncパイプを使用する必要があります。

<tr *ngFor="let item of productList | async">

この場合、async-pipeがサブスクリプションを行います:)

3
AJT82