Reputation: 1035
I am pretty new in Angular2/TypeScript so please excuse me if I am doing some stupid mistake. What I am trying to do is from Select drop down I am populating the data using service which is returning me a JSON array.
Here is my 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
(used for to populate drop down list):
export class Product {
constructor(
public ptypeid: number,
public name: string
) { }
}
products.ts
(used for to populate data from 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
}
]
If I define my getProducts()
as getProductTypeList()
then it's perfectly populating the data in my view (Where if I select Unit trust from the drop down then it should populate relevant data). But if I use as api url instead it's giving me below error:
Type 'Observable<any>' is not assignable to type 'Products[]'. Property 'length' is missing in type 'Observable<any>'
I don't understand how to resolve this error. Can anyone please help me in this. Thanks in advance.
Upvotes: 21
Views: 127365
Reputation: 136144
productList
should be Product[]
not Observable<any>
. So assign productList
value from getProducts
subscribe method, where you will retrieve an array of Product
onSelect(typeid) {
this.productService.getProducts()
.pipe(
map((products) => products.filter(p => p.ptypeid === typeid))
)
.subscribe((products) => {
this.productList = products;
});
}
Upvotes: 15
Reputation: 300
The number of variables in the TypeScript and HTML must be the same.
TypeScript:
export class Products {
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
}
HTML:
<table>
<tr *ngFor="let item of productList">
<td>{{ item.id }}</td>
<td>{{ item.ptypeid}}</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>
Upvotes: -1
Reputation: 73357
A couple of problems, first I noticed you are using a relative url for your get-request. That is not going to work. You need to have the correct url, meaning something that starts with http://..
even if your api is on localhost you need to provide the complete url.
Secondly, the get request is okay, but your call in your component should look like this:
this.productService.getProducts()
.subscribe(data => {
this.productList = data})
Since you are doing a map in your request, you also need to subscribe to that, otherwise you won't get any results!
Worth mentioning is also, since this is an async operation, you might want to include a ngIf
in your table, so that your app won't throw an error in case view is rendered before data has arrived, so just do this:
<table *ngIf="productList">
This should clear things up!
Alternatively, if you do not want to subscribe, you can do as you previously did:
this.products = this.productService.getProductTypeList();
but then you have to use the async
pipe in the view:
<tr *ngFor="let item of productList | async">
In this case the async-pipe does the subscription for you :)
Upvotes: 3
Reputation: 3867
Change your method getProducts method to
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;
}
Upvotes: 5