A Beginner's Guide to Reactive Programming in Angular 18 - Part 1
App Setup
Open a Terminal
Install Angular CLI -
npm install -g @angular/cli
Create a new project -
ng new reactive-angular-app
Run the project locally -
cd reactive-angular-app
andnpm start
The app would be running locally now at
http://localhost:4200
Creating Routes, Components, Service and Interface
Navigate to the app folder under the src folder. You will find a file named app.routes.ts, which will have empty routes in it.
export const routes: Routes = [];
We will add routes for Product Page and Cart Page as below. Also we will add a redirect route to product page when the application loads. Wild card routes we have not added for sake of simplicity.
export const routes: Routes = [
{ path: '', redirectTo:'product', pathMatch: 'full' },
{ path: 'product', title: 'Product Page', component: ProductComponent },
{ path: 'cart', title: 'Cart Page', component: CartComponent },
];
Next, we will create the Product Component, Cart Component, Product Service, and Product Interface using the code below.
ng generate component product
ng generate component cart
ng generate service service/product
ng generate interface model/product
Adding Logic to the Component and Service
Inside the product.service.ts file, we will write the logic to get products. We will use the dummyjson API for our examples. For demonstration purposes, we will fetch only selected items.
// model/product.ts
export interface Product {
id: number;
title: string;
price: number;
discountPercentage: number;
rating: number;
images: string[];
}
export interface ProductResponse {
products: Product[];
total: number;
skip: number;
limit: number;
}
// product.service.ts
import { Injectable } from '@angular/core';
import { Observable, map, catchError, throwError } from 'rxjs';
import { Product, ProductResponse } from "../model/product";
@Injectable({
providedIn: 'root'
})
export class ProductService {
private readonly productsUrl = 'https://dummyjson.com/products?limit=10&select=id,title,price,images,discountPercentage,rating';
constructor(private http: HttpClient) { }
getProducts(): Observable<Product[]> {
return this.http.get<ProductResponse>(`this.productsUrl`,)
.pipe(
map((response: ProductResponse) => response.products),
catchError((err: any) => {
return throwError(() => new Error('Could not load products'));
})
);
}
}
// product.component.ts
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { Product } from '../model/shopping';
import { AsyncPipe, CommonModule } from '@angular/common';
import { ProductService } from '../service/product.service';
@Component({
selector: 'app-product',
standalone: true,
imports: [AsyncPipe, CommonModule,],
templateUrl: './product.component.html',
styleUrl: './product.component.css'
})
export class ProductComponent {
constructor(private productService: ProductService) {}
products$: Observable<Product[]> = this.productService.getProducts();
}
//product.component.html
<div class="bg-white">
<div
class="container mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24 lg:max-w-7xl lg:px-8"
>
<h2 class="text-2xl font-bold tracking-tight text-gray-900">
Products Page
</h2>
<ng-container *ngIf="products$ | async as products; else loading">
<div
class="mt-6 grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-3 lg:grid-cols-4 xl:gap-x-8"
>
<div
*ngFor="let product of products"
class="group relative bg-white rounded-lg overflow-hidden border border-slate-200 flex flex-col"
>
<div class="overflow-hidden bg-gray-200 group-hover:opacity-75 h-44">
<img
[src]="product.images[0]"
alt="{{ product.title }}"
class="h-full w-full"
/>
<div
*ngIf="product.discountPercentage"
class="absolute top-0 right-0"
>
<p class="bg-red-500 text-white text-xs px-2 py-1">
Discount: {{ product.discountPercentage }}%
</p>
</div>
</div>
<div class="flex-grow flex flex-col">
<div class="mt-auto p-4">
<h3 class="text-sm text-gray-700">
<span aria-hidden="true"></span>
{{ product.title }}
</h3>
<p class="text-lg font-medium text-gray-900 mt-2">
${{ product.price }}
</p>
<p class="text-blue-400 mt-2">Rating: {{ product.rating }}/5</p>
</div>
<button
(click)="addToCart(product)"
class="bg-slate-100 text-black w-full px-4 py-2 rounded hover:bg-slate-300 mt-4"
>
Add to Cart
</button>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<ng-template #loading>
<div class="flex justify-center items-center h-screen">
<p>Loading products...</p>
</div>
</ng-template>
To be continued in second part.
Subscribe to my newsletter
Read articles from mahesh samagandi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by