Categories

Friday, November 22, 2024
#919814419350 therichposts@gmail.com
AngularAngular 17Angular Ecommerce Templates

Shopping Cart using Signals Angular (17+)

Shopping Cart using Signals Angular (17+)

Hello everyone, if you’re in search of a shopping cart in Angular 17+, then you’ve come to the right place! Today this blog post I will show you Shopping Cart using Signals Angular (17+).

Live Demo

Angular 17 came and Bootstrap 5 also. If you are new then you must check below two links:

Guys now here is the complete code snippet for Shopping Cart using Signals Angular (17+):

1. Firstly friends we need fresh angular 17 setup and for this we need to run below commands but if you already have angular 17 setup then you can avoid below commands. Secondly we should also have latest node version installed on our system:

npm install -g @angular/cli 

ng new angularcart//Create new Angular Project

cd angularcart// Go inside the Angular Project Folder

2. Guys now we need to run below commands to create components to our angular application:

ng g c shopping-cart

3. Now guys we need to add below code into our scr/app/app.component.html file for main output:

<router-outlet></router-outlet>

4. Guys now we need to create new file `mock.items.ts` inside shopping-cart folder and add below code inside it and we wil have few demo items:

export const mockItems: any[] = [
    {
      icon: '????',
      productName: 'Avocado',
      productId: '001',
      quantity: 2,
      price: 12,
    },
    {
      icon: '????',
      productName: 'Apples',
      productId: '002',
      quantity: 1,
      price: 22,
    },
    {
      icon: '????',
      productName: 'Carrots',
      productId: '003',
      quantity: 1,
      price: 32,
    },
  ];
  

5. Now guys create new file `item.icons.ts` inside shopping-cart folder and add below code inside that file:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-item-with-icon',
  standalone: true,
  template: `
    <div>
      <span class="item-icon">{{ item.icon }}</span>
      <span class="item-details">
        <b>{{ item.productName }}</b> - {{ item.quantity }} x £{{ item.price }}
      </span>
    </div>
  `,
  styles: [
    `
    .item-icon {
      font-size: 24px;
    }

    .item-details {
      margin-left: 10px;
    }
  `,
  ],
})
export class ItemWithIconComponent {
  @Input() item: any;
}

6. Now guys create new file `cart.service.ts` inside shopping-cart folder and add below code inside it:

import { Injectable, signal } from '@angular/core';
import { CartItem, ShoppingCart } from './cart-item.interface';
import { mockItems } from './mock.items';

@Injectable({
  providedIn: 'root',
})
export class CartService {
  cart = signal<ShoppingCart>({
    items: mockItems,
    totalAmount: this.calculateTotalAmount(mockItems),
  });

  private calculateTotalAmount(items: CartItem[]): number {
    return items.reduce((total, item) => total + item.price * item.quantity, 0);
  }
  addItem(item: CartItem) {
    this.cart.update((currentCart) => {
      const existingItem = currentCart.items.find(
        (i) => i.productId === item.productId
      );

      if (existingItem) {
        // Increment quantity if item already exists
        existingItem.quantity += item.quantity;
      } else {
        // Add the new item if it doesn't exist
        currentCart.items.push(item);
      }

      currentCart.totalAmount += item.price * item.quantity;

      return currentCart;
    });
  }

  removeItem(productId: string) {
    this.cart.update((currentCart) => {
      const item = currentCart.items.find((i) => i.productId === productId);

      if (item) {
        currentCart.totalAmount -= item.price * item.quantity;
        currentCart.items = currentCart.items.filter(
          (i) => i.productId !== productId
        );
      }

      return currentCart;
    });
  }
}

7. Now guys create new file `cart-item.interface.ts` inside shopping-cart folder and add below code inside it:

export interface CartItem {
    productId: string;
    productName: string;
    price: number;
    quantity: number;
  }
  
  export interface ShoppingCart {
    items: CartItem[];
    totalAmount: number;
  }
  

8. Now guys add below code inside app/app.routes.ts file:

import { Routes } from '@angular/router';

import { ShoppingCartComponent } from './shopping-cart/shopping-cart.component';
export const routes: Routes = [
      {
        path: '', title: 'Dashboard Page', component: ShoppingCartComponent,
      }
];

9. Now guys add below code inside app/shopping-cart/shopping-cart.component.ts file:

import { Component } from '@angular/core';
import { CartService } from './cart.service';
import { CommonModule } from '@angular/common';
import { ItemWithIconComponent } from './item.icons';
@Component({
  selector: 'app-shopping-cart',
  standalone: true,
  imports: [CommonModule, ItemWithIconComponent],
  styles: [
    `
    div {
      font-family: 'Arial', sans-serif;
      max-width: 600px;
      margin: 0 auto;
      padding: 20px;
    }

    h1 {
      color: #333;
    }

    .cart-item {
      margin-bottom: 15px;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 5px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .product-info {
      flex-grow: 1;
    }

    .remove-button {
      background-color: #dc3545;
      color: #fff;
      border: none;
      padding: 5px 10px;
      border-radius: 3px;
      cursor: pointer;
    }

    .total-amount {
      margin-top: 15px;
      font-size: 18px;
    }

    .add-button {
      background-color: #28a745;
      color: #fff;
      border: none;
      padding: 10px 20px;
      border-radius: 3px;
      cursor: pointer;
    }
    .discount {
      margin-left: 15px;
    }
    .discount:disabled {
      background-color: #ccc;
      cursor: not-allowed;
    }
  `,
  ],
  template: `
    <div>
      <h1>Shopping Cart using Signals Angular (17+)</h1>

      <div *ngFor="let item of cartItems" class="cart-item">
        <div class="product-info">
         <app-item-with-icon [item]="item"></app-item-with-icon>
        </div>
        <button (click)="removeItem(item.productId)" class="remove-button">Remove</button>
        <!-- <p>{{ item | json }}</p> -->
      </div>

      <hr>

      <div class="total-amount">
        <strong>Total:</strong> £{{ totalAmount }}
      </div>
      <button (click)="addItem()" class="add-button">???? Add Item</button>
      <button (click)="applyDiscount()" [disabled]="isDiscountApplied" class="add-button discount">???? Apply Discount 10%</button>
    </div>
  `,
})
export class ShoppingCartComponent {
  cartItems = this.cartService.cart().items;
  totalAmount = this.cartService.cart().totalAmount;
  isDiscountApplied = false;

  constructor(private cartService: CartService) {}

  addItem() {
    // fixed added product
    const newItem: any = {
      icon: '????',
      productName: 'bananas',
      productId: '004',
      quantity: 1,
      price: 10,
    };

    this.cartService.addItem(newItem);
    this.udpateCart();
  }

  removeItem(productId: string) {
    this.cartService.removeItem(productId);
    this.udpateCart();
  }

  udpateCart() {
    // Update cartItems and totalAmount after removing an item
    this.cartItems = this.cartService.cart().items;
    this.totalAmount = this.cartService.cart().totalAmount;
  }

  applyDiscount() {
    if (!this.isDiscountApplied) {
      //  subtract 10%
      this.totalAmount -= this.totalAmount * 0.1;
      this.isDiscountApplied = true;
    }
  }
}

Friends in the end must run ng serve command into your terminal to run the angular 17 project(localhost:4200).

Now we are done friends. If you have any kind of query, suggestion and new requirement then feel free to comment below.

Note: Friends, In this post, I just tell the basic setup and things, you can change the code according to your requirements.

I will appreciate that if you will tell your views for this post. Nothing matters if your views will be good or bad because with your views, I will make my next posts more good and helpful.

Jassa

Thanks

therichpost
the authortherichpost
Hello to all. Welcome to therichpost.com. Myself Ajay Malhotra and I am freelance full stack developer. I love coding. I know WordPress, Core php, Angularjs, Angular 19, MedusaJs, Next.js, Bootstrap 5, Nodejs, Laravel, Codeigniter, Shopify, Squarespace, jQuery, Google Map Api, Vuejs, Reactjs, Big commerce etc.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.