web-dev-qa-db-fra.com

Le type 'Observable <any>' n'est pas assignable au type '[]'

Je suis assez nouveau dans Angular2/TypeScript, alors veuillez m'excuser si je commets une erreur stupide. Ce que j'essaie de faire, c'est de sélectionner la liste déroulante Je renseigne les données à l'aide du service qui me renvoie un tableau JSON.

Voici mon code:

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 (Utilisé pour remplir la liste déroulante):

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

products.ts (Utilisé pour remplir les données du service):

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
      }
]

Si je définis ma getProducts() comme getProductTypeList(), elle remplit parfaitement les données dans ma vue (où, si je sélectionne la confiance de l'unité dans la liste déroulante, elle devrait renseigner les données pertinentes). Mais si j'utilise plutôt comme adresse URL, cela me donne l'erreur suivante:

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

Je ne comprends pas comment résoudre cette erreur. Quelqu'un peut-il m'aider s'il vous plaît dans ce domaine. Merci d'avance.

14
tutorialfeed

productList devrait être Product[] ne pas Observable<any>. Donc assigner productList valeur de la méthode getProducts subscribe, où vous récupérerez un tableau de Product

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

Changez votre méthode getProducts en

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

Quelques problèmes, d’abord, j’ai remarqué que vous utilisiez une URL relative pour votre requête get. Cela ne va pas au travail. Vous devez avoir l'URL correcte, ce qui signifie quelque chose qui commence par http://.. même si votre api est sur localhost, vous devez fournir l'URL complète.

Deuxièmement, la requête get est acceptable, mais votre appel dans votre composant doit ressembler à ceci:

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

Puisque vous faites une carte dans votre demande, vous devez également vous y abonner, sinon vous n'obtiendrez aucun résultat!

Il convient également de noter qu’étant une opération asynchrone, vous pouvez inclure un ngIf dans votre table, de sorte que votre application ne génère pas d’erreur si la vue est rendue avant que les données ne soient arrivées. faire ceci:

<table *ngIf="productList">

Cela devrait éclaircir les choses!

Si vous ne souhaitez pas vous abonner, vous pouvez également procéder comme vous le faisiez précédemment:

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

mais ensuite vous devez utiliser le pipe async dans la vue:

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

Dans ce cas, async-pipe fait la souscription pour vous :)

3
AJT82