Activity 31: Angular Ecommerce Product List

Photo by Jess Bailey on Unsplash

Activity 31: Angular Ecommerce Product List

In this guide, I'll walk you through creating a responsive Angular-based e-commerce product list that utilizes Object Data Structures. We'll make use of services to manage product data and display it dynamically in a grid layout. We'll also employ Flexbox and CSS Grid for layout and follow the BEM CSS architecture for styling.

Product Model

We need to create a model for our products. This will define the structure of the product objects, which will be used throughout the application.

Create a file product.model.ts:

export interface Product {
    id: number;
    name: string;
    description: string;
    price: string;
    imageUrl: string;
  }

This model ensures we have a structured format for each product.

Creating the Product Service

Next, we need a service to manage the product data. We’ll add a list of products with placeholder image URLs.

Create the service product.service.ts:

import { Injectable } from '@angular/core';
import { Product } from './product.model';

@Injectable({
  providedIn: 'root',
})
export class ProductService {
  getProducts(): Product[] {
    return [
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },
      {
        id: 1,
        name: 'Bluetooth Speaker',
        description: 'Portable with excellent sound.',
        price: '1000',
        imageUrl: 'image/speaker.jpg',
      },



    ];
  }
}

This component fetches the list of products from the service and stores them in the products array.

Displaying the Products in the Component

Now, we need to fetch and display the product data in the component. We'll be using Flexbox and CSS Grid for the layout.

Create the component product.component.ts:

import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProductService } from './product.service';

@Component({
  selector: 'app-product',
  standalone: true,
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css'],
  imports: [CommonModule], 
  providers: [ProductService], 
})
export class ProductComponent implements OnInit {
  products: any[] = []; 

  constructor(private productService: ProductService) {}

  ngOnInit(): void {

    this.products = this.productService.getProducts();
  }
}

Designing the Layout with Grid and Flex

We’ll be using CSS Grid for the overall layout and Flexbox within the individual product cards to align elements.

Create the layout in product.component.html:

<main class="product-container">
    <div class="product-card" *ngFor="let product of products">
      <img class="product-card__image" [src]="product.imageUrl" [alt]="product.name" />
      <h3 class="product-card__title">{{ product.name }}</h3>
      <p class="product-card__description">{{ product.description }}</p>
      <p class="product-card__price">₱{{ product.price }}</p>
      <button class="product-card__button--primary" (click)="addToCart(product)">Add to Cart</button>
      <button class="product-card__button--secondary" (click)="addToWishlist(product)">Wishlist</button>
    </div>
  </main>

This HTML uses *ngFor to loop over the products and display them in individual cards.

BEM CSS Architecture for Styling

Now, let’s apply BEM CSS architecture to our styles for maintainability and clarity.

Create the CSS for the layout in product.component.css:


.product-grid {
    display: grid;
    gap: 20px;
    grid-template-columns: repeat(2, 1fr); /* Mobile */
    padding: 20px;
  }

  @media (min-width: 768px) {
    .product-grid {
      grid-template-columns: repeat(3, 1fr); /* Tablet */
    }
  }

  @media (min-width: 1024px) {
    .product-grid {
      grid-template-columns: repeat(5, 1fr); /* Desktop */
    }
  }

  .product-card {
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 8px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    text-align: center;
    display: flex;
    flex-direction: column;
    padding: 15px;
    transition: transform 0.3s ease;
  }

  .product-card:hover {
    transform: translateY(-5px);
  }

  .product-card__image {
    width: 100%;
    height: 180px;
    object-fit: cover;
    border-radius: 4px;
  }

  .product-card__badges {
    margin: 10px 0;
  }

  .badge {
    display: inline-block;
    padding: 4px 8px;
    border-radius: 12px;
    font-size: 0.8rem;
    font-weight: bold;
    margin-right: 5px;
  }

  .badge--primary {
    background-color: #007bff;
    color: #fff;
  }

  .badge--secondary {
    background-color: #6c757d;
    color: #fff;
  }

  .product-card__title {
    font-size: 1.2rem;
    margin: 10px 0 5px;
    color: #333;
  }

  .product-card__description {
    font-size: 0.9rem;
    color: #666;
    margin-bottom: 15px;
  }

  .product-card__buttons {
    margin-top: auto;
  }

  .button {
    padding: 8px 15px;
    border: none;
    border-radius: 4px;
    font-size: 0.9rem;
    cursor: pointer;
    margin: 5px;
    transition: background-color 0.3s ease;
  }

  .button--primary {
    background-color: #007bff;
    color: #fff;
  }

  .button--primary:hover {
    background-color: #0056b3;
  }

  .button--secondary {
    background-color: #6c757d;
    color: #fff;
  }

  .button--secondary:hover {
    background-color: #5a6268;
  }
  • The .product-container uses CSS Grid for the overall layout with responsive columns based on the screen size.

  • Each product card uses Flexbox to align items vertically.

  • 2 columns for mobile, 3 columns for tablets, and 5 columns for desktops.

GitHub Link: https://github.com/RodelDecio/Angular-Ecommerce-Product-List.git

Hosting URL: https://angularecommerceproductl-35506.web.app