So far, I haven't found a simple example of how to push data into an array in Angular 2. In AngularJs it was easy (example), but I'm struggling for it in Angular 2, maybe because I'm using router and I don't know how to configure it (I was following the angular heroes example).
What I want to do, the whole solution:
app.module.ts:
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
import { HttpModule } from '@angular/http';
import { ProductsService } from '../services/ProductsService';
import { AppComponent } from "./components/app";
import { Products } from "./components/products";
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot([
{
path: 'products/:class_id/:type_id',
component: Products
}
], { useHash: true })
],
exports: [RouterModule],
declarations: [
AppComponent
Products
],
providers: [
ProductsService
],
bootstrap: [AppComponent]
})
export class AppModule { }
AppComponent.ts
import { Component} from "@angular/core";
@Component({
selector: "my-app",
template: `<div>
<a [routerLink]="['/products', 1, 1]">Products-1</a>
<a [routerLink]="['/products', 2, 2]">Products-2</a>
</div>`
})
export class AppComponent{}
ProductsService.ts
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
@Injectable()
export class ProductsService {
private headers = new Headers({ 'Content-Type': 'application/json' });
constructor(private http: Http) { }
getProducts(class_id: string, type_id: string, index: number, numberOfObjectsPerPage: number): Promise<any> {
return this.http.get('Home/GetProducts?pageIndex=' + index +'&classId=' + class_id + '&typeId=' + type_id)
.toPromise()
.then(response => response.json() as any)
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
Product.ts
import 'rxjs/add/operator/switchMap';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import * as $ from 'jquery';
import { ProductsService } from '../../services/ProductsService';
import { Product } from '../../common/models/Product';
@Component({
selector: 'products',
templateUrl: 'Products.html',
})
export class Products implements OnInit {
products: Array<Product> = [];
numberOfObjectsPerPage: number = 10;
index: number = 0;
constructor(
private productsService: ProductsService,
private route: ActivatedRoute
) {}
ngOnInit(): void {
this.loadProducts();
}
loadProducts():void{
this.route.paramMap
.switchMap((params: ParamMap) =>
this.productsService.getProducts(params.get('class_id'), params.get('type_id'), this.index, this.numberOfObjectsPerPage))
.subscribe(products => {
this.products = products;
});
}
showMore():void{
this.index++;
this.loadProducts();
}
}
Products.html:
<div class="product" *ngFor="let product of products;">
{{ product.name }}
</div>
<button (click)="showMore()">Show more</button>
So, what is the problem here: if I go to Products-1
I get 10 products, which is obvious, but if I press Show more
then the first 10 products are removed and another 10 are shown - which again is obvious, so to avoid this and keep the first 10 and load 10 more, I replaced Product.ts -> this.products = products;
to:
for (let i = 0; i < products.length; i++) {
this.products.push(products[i]);
}
Another problem appears now: when I go to Product-2
, the products from Products-1
are shown along with the products of Product-2
, so to avoid this, I added this two lines into the Product.ts constructor:
constructor(private productsService: ProductsService, private route: ActivatedRoute) {
route.paramMap.subscribe(params => this.products = []);
route.paramMap.subscribe(params => this.index = 0);
}
Now, everything works just fine except: when I go from Products-1
to Products-2
and load more products, and after that return to Products-1
, I can see in my network tab that multiple requests of same type are being send to my server.
So my questions are:
Instead of “href” attribute of anchor tag, we use the “routerLink” attribute of Angular. The routerLink attribute allows us to link to a specific route of the Application.
There are several things that I would add/change in product.ts
:
Add those properties under your index: number = 0;
property:
class_id: string;
type_id: string;
Remove route.paramMap.subscribe
from the constructor
ngOnInit
, should look like this:
ngOnInit(): void {
this.route.paramMap.subscribe(params => {
this.products = [];
this.index = 0;
this.type_id = params.get('type_id');
this.class_id = params.get('class_id');
this.loadProducts();
});
}
And finally, loadProducts()
:
loadProducts(): void {
this.productsService.getProducts(this.class_id, this.type_id, this.index, this.numberOfObjectsPerPage).then(
productArray => {
this.products = this.products.concat(productArray);
})
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With