2017-01-24 8 views
9

Jestem całkiem nowy w Angular2/TypeScript, więc przepraszam, jeśli popełniam jakiś głupi błąd. Próbuję to zrobić z menu rozwijanego Wybierz, że zapełniam dane przy użyciu usługi, która zwraca mi tablicę JSON.Typ 'Observable <any>' nie można przypisać '[]'

Oto mój kod:

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 (używany do do wypełnienia listy rozwijanej):

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

products.ts (używany do do wypełnienia danych z serwisu):

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

Gdybym określić mój getProducts() jak getProductTypeList() wtedy to doskonale wypełniania danych moim zdaniem (gdzie jeśli wybiorę powierniczego z rozwijanego następnie powinien wypełnić odpowiednie dane). Ale jeśli mogę użyć jako api URL zamiast to daje mi poniżej błędu:

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

Nie rozumiem, w jaki sposób rozwiązać ten błąd. Czy ktoś może mi w tym pomóc? Z góry dziękuję.

+0

Czy udało Ci się rozwiązać swój zauważalny problem? – wladyband

Odpowiedz

5

productList powinien być Product[] nie Observable<any>. Więc przypisać productList wartość z getProducts subskrybować metodę, gdzie można pobrać tablicę Product

onSelect(typeid) { 
    this.productService.getProducts() 
    .filter((item)=>item.ptypeid == typeid) 
    .subscribe((products) => { 
     this.productList = products; 
    }); 
} 
+0

Nadal nie mogę go pobrać. Nawet nie jest w stanie wejść pod tym .subscribe ((products) => { this.productList = products; }) – tutorialfeed

+0

@tutorialfeed czy nadal otrzymujesz błąd podczas kompilacji? –

+0

Wystąpił błąd, ale nie otrzymuję danych. – tutorialfeed

3

zmienić metodę metoda getProducts do

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; 
} 
+0

Ten również nie działa. – tutorialfeed

3

kilka problemów, najpierw zauważyłem używasz względny adres URL dla twojego żądania otrzymania. To się nie uda. Musisz mieć poprawny adres URL, co oznacza, że ​​zaczyna się od http://.., nawet jeśli Twój api znajduje się na localhost, musisz podać pełny adres URL.

drugie, żądanie GET jest w porządku, ale połączenie w składniku powinna wyglądać następująco:

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

Ponieważ robisz mapę w swoim wniosku, trzeba także zapisać się, że w przeciwnym razie nie uzyska żadnych wyników!

Warto również wspomnieć, że ponieważ jest to operacja asynchroniczna, możesz umieścić w tabeli tabelę ngIf, aby aplikacja nie wyświetlała błędu w przypadku, gdy widok zostanie wyświetlony przed nadejściem danych, więc po prostu wykonaj to:

<table *ngIf="productList"> 

To powinno wyjaśnić sprawę!

Ewentualnie, jeśli nie chce się zapisać, można to zrobić, jak wcześniej uczynił:

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

ale wtedy trzeba użyć rury async w widoku:

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

W w tym przypadku async-pipe robi dla ciebie subskrypcję :)

+0

Przez ograniczony czas, jest to działający plunker z fałszywym backendem: https://plnkr.co/edit/oxgy93cEFM5USf07xeIL?p=preview Nie uwzględniono go w odpowiedzi, ponieważ używa się doładowania i nie pozostanie uruchomiony na zawsze, ale jeśli nie masz pewności, możesz sprawdzić błąd i porównać go z kodem, a kiedy skończysz, zgaduję, że usunę ten komentarz;) – Alex

+0

@tutorialfeed, czy to rozwiązanie pomogło ci? :) – Alex

Powiązane problemy