🧱 Lecture 9B : Product Management (Angular)

Published: (December 5, 2025 at 12:54 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Introduction

This module focuses on building complete product management functionality, including full CRUD operations and seamless integration between the frontend interface and backend APIs. It ensures that users can create, update, view, and delete products efficiently while maintaining a smooth and responsive experience across the system.

Administrators will be able to:

  • Manage products
  • Communicate with the backend APIs you’ve already built

Topics Covered

  • Auth Guard
  • Full CRUD page for Product
  • Product Service
  • Product Route
  • Update App Routes
  • Update Menu

Auth Guard

Path: src/app/services/authguard/auth-guard.service.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AuthApiService } from '../api/auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuardService {
  constructor(
    private authService: AuthApiService,
    private router: Router
  ) {}

  canActivate(): boolean {
    const token = this.authService.getToken();
    const refreshToken = this.authService.getRefreshToken();

    // If no token and no refresh token, redirect to login
    if (!token && !refreshToken) {
      this.router.navigate(['/auth/login']);
      return false;
    }

    // If no token but refresh token exists, try to refresh
    if (!token && refreshToken) {
      this.attemptTokenRefresh(refreshToken);
      return false; // Wait for refresh attempt
    }

    // If token exists, user is authenticated
    if (token) {
      return true;
    }

    return false;
  }

  private attemptTokenRefresh(refreshToken: string): void {
    this.authService.refresh({ token: '', refreshToken }).subscribe({
      next: () => {
        // Token refreshed successfully, reload current route
        this.router.navigate([this.router.url]);
      },
      error: () => {
        // Refresh failed, redirect to login
        this.authService.logout();
        this.router.navigate(['/auth/login']);
      }
    });
  }
}

UI Pages using PrimeNG

Create the following three files for the Product feature:

  • src/app/features/products/product/product.html
  • src/app/features/products/product/product.scss (blank file)
  • src/app/features/products/product/product.ts

product.html

<div class="card">
  <p-toolbar>
    <ng-template pTemplate="left">
      <button pButton label="Manage Products" class="p-button-success"></button>
    </ng-template>
  </p-toolbar>

  <p-table #dt [value]="products" [paginator]="true" [rows]="10" responsiveLayout="scroll">
    <ng-template pTemplate="header">
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Description</th>
        <th>Price</th>
        <th>Stock</th>
      </tr>
    </ng-template>
    <ng-template pTemplate="body" let-product>
      <tr>
        <td>{{ product.id }}</td>
        <td>{{ product.name }}</td>
        <td>{{ product.description }}</td>
        <td>{{ product.price | currency: 'USD' }}</td>
        <td>{{ product.stock }}</td>
      </tr>
    </ng-template>
  </p-table>

  <p-dialog header="Add Product" [(visible)]="displayDialog" [modal]="true" [responsive]="true">
    <div class="p-fluid">
      <div class="p-field">
        <label for="name">Name</label>
        <input id="name" type="text" pInputText [(ngModel)]="product.name" required />
        <small class="p-error">Name is required.</small>
      </div>

      <div class="p-field">
        <label for="description">Description</label>
        <textarea id="description" pInputTextarea [(ngModel)]="product.description"></textarea>
      </div>

      <div class="p-field">
        <label for="price">Price</label>
        <input id="price" type="number" pInputText [(ngModel)]="product.price" />
      </div>

      <div class="p-field">
        <label for="stock">Stock</label>
        <input id="stock" type="number" pInputText [(ngModel)]="product.stock" />
      </div>
    </div>
  </p-dialog>
</div>

product.scss

product.ts

import { Component, OnInit, signal, ViewChild } from '@angular/core';
import { ConfirmationService, MessageService } from 'primeng/api';
import { Table, TableModule } from 'primeng/table';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ButtonModule } from 'primeng/button';
import { RippleModule } from 'primeng/ripple';
import { ToastModule } from 'primeng/toast';
import { ToolbarModule } from 'primeng/toolbar';
import { RatingModule } from 'primeng/rating';
import { InputTextModule } from 'primeng/inputtext';
import { TextareaModule } from 'primeng/textarea';
import { SelectModule } from 'primeng/select';
import { Radi
Back to Blog

Related posts

Read more »

Angular pipes: Time to rethink

Forem Communities Forem !Forem Logohttps://media2.dev.to/dynamic/image/width=65,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3...