-->

Friday, November 29, 2024

Library Management Project in AngularJS and ASP.NET CORE RESTFUL API

 Today, we are going to create a new project in Angular, which will be called the Library Management System. As you all know, a Library Management System has several key functionalities. The library contains books, each of which has an author, and books are categorized into different types. There are two types of users in the library: the admin and the student.




Now, let's start building the Library Management System in AngularJS. First, we will create a registration form that will include three fields: username, password, and confirm password. Our first task will be to implement validation for the confirm password field. Next, we will send the username and password to the API using a service through reactive forms. In this project, we will be using the ASP.NET Core RESTful API.

Step-1:  ng new library-management-system

Step-2:   ng g c credentials/registration --skip-tests


Html Part of Registration form

<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">

  <div>

    <label for="username">Username</label>

    <input id="username" formControlName="username" type="text">

    <div *ngIf="username.invalid && (username.dirty || username.touched)">

      <div *ngIf="username.errors?.['required']">Username is required.</div>

    </div>

  </div>


  <div>

    <label for="password">Password</label>

    <input id="password" formControlName="password" type="password">

    <div *ngIf="password.invalid && (password.dirty || password.touched)">

      <div *ngIf="password.errors?.['required']">Password is required.</div>

    </div>

  </div>


  <div>

    <label for="confirmPassword">Confirm Password</label>

    <input id="confirmPassword" formControlName="confirmPassword" type="password">

    <div *ngIf="confirmPassword.invalid && (confirmPassword.dirty || confirmPassword.touched)">

      <div *ngIf="confirmPassword.errors?.['required']">Confirm Password is required.</div>

      <div *ngIf="confirmPassword.errors?.['passwordMismatch']">Passwords do not match.</div>

    </div>

  </div>


  <button type="submit" [disabled]="registrationForm.invalid">Register</button>

</form>

Type Script File 

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

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

import { UserService } from './user.service'; 


@Component({

  selector: 'app-registration',

  templateUrl: './registration.component.html',

  styleUrls: ['./registration.component.css']

})

export class RegistrationComponent implements OnInit {

  registrationForm: FormGroup;


  constructor(private fb: FormBuilder, private userService: UserService) {}


  ngOnInit(): void {

    this.registrationForm = this.fb.group({

      username: ['', Validators.required],

      password: ['', Validators.required],

      confirmPassword: ['', Validators.required]

    }, {

      validator: this.passwordMatchValidator

    });

  }


  get username() {

    return this.registrationForm.get('username');

  }


  get password() {

    return this.registrationForm.get('password');

  }


  get confirmPassword() {

    return this.registrationForm.get('confirmPassword');

  }

  passwordMatchValidator(form: FormGroup): { [key: string]: boolean } | null {

    return form.get('password')?.value === form.get('confirmPassword')?.value

      ? null : { 'passwordMismatch': true };

  }


  onSubmit(): void {

    if (this.registrationForm.valid) {

      const userData = this.registrationForm.value;

      this.userService.registerUser(userData).subscribe(response => {

        console.log('User registered successfully!', response);

      });

    }

  }

}


Step-3 :  ng g s Credentials/user --skip-tests

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs';


@Injectable({

  providedIn: 'root'

})

export class UserService {

  private apiUrl = 'https://your-api-url.com/register';


  constructor(private http: HttpClient) {}


  registerUser(userData: userModel): Observable<ResponseDto> {

    return this.http.post(this.apiUrl, userData);

  }

}

After registration, we will receive a confirmation message from the API, indicating that the registration is complete. Next, we will design the login form, which will include two fields: username and password. Using a service, we will send the login data to the API URL via a POST request. From the API, we will receive a token, which we will save in the browser's internal storage.

Steo-4 : ng g c Credentails/login


<form [formGroup]="loginForm" (ngSubmit)="onLogin()">

  <div>

    <label for="username">Username</label>

    <input id="username" formControlName="username" type="text">

    <div *ngIf="username.invalid && (username.dirty || username.touched)">

      <div *ngIf="username.errors?.['required']">Username is required.</div>

    </div>

  </div>


  <div>

    <label for="password">Password</label>

    <input id="password" formControlName="password" type="password">

    <div *ngIf="password.invalid && (password.dirty || password.touched)">

      <div *ngIf="password.errors?.['required']">Password is required.</div>

    </div>

  </div>


  <button type="submit" [disabled]="loginForm.invalid">Login</button>

</form>



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

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

import { AuthService } from './auth.service'; // Import your auth service here


@Component({

  selector: 'app-login',

  templateUrl: './login.component.html',

  styleUrls: ['./login.component.css']

})

export class LoginComponent implements OnInit {

  loginForm: FormGroup;


  constructor(private fb: FormBuilder, private authService: AuthService) {}


  ngOnInit(): void {

    this.loginForm = this.fb.group({

      username: ['', Validators.required],

      password: ['', Validators.required]

    });

  }


  get username() {

    return this.loginForm.get('username');

  }


  get password() {

    return this.loginForm.get('password');

  }


  onLogin(): void {

    if (this.loginForm.valid) {

      const loginData = this.loginForm.value;

      this.authService.loginUser(loginData).subscribe(response => {

        

        localStorage.setItem('authToken', response.token);

        console.log('Login successful! Token saved.');

      }, error => {

        console.error('Login failed', error);

      });

    }

  }

}

Now, let's move on to issuing books. Before issuing a book, we need to log in the admin. Once the admin logs in, they will receive a token from the API, which will include the user's role. Based on this role, we can hide or display menu items in AngularJS.

ng g s Credentails/auth --skip-tests

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs';


@Injectable({

  providedIn: 'root'

})

export class AuthService {

  private apiUrl = 'https://your-api-url.com/login';


  constructor(private http: HttpClient) {}


  loginUser(loginData: any): Observable<any> {

    return this.http.post<any>(this.apiUrl, loginData);

  }

}

import { HttpClient, HttpHeaders } from '@angular/common/http';

const token = localStorage.getItem('authToken');

const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);

this.http.get('https://your-api-url.com/protected-route', { headers })

  .subscribe(response => {

    console.log('Protected data', response);

  });


The menu design needs to be done in such a way that the menu items are shown or hidden based on the user's role."

When the admin logs in, the menu items will be different compared to when a student logs in. First, we will log in the admin, and the menu items will be as follows: Home, Category, Author, Book, and Issue and Return History.

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs';


@Injectable({

  providedIn: 'root'

})

export class AuthService {

  private apiUrl = 'https://your-api-url.com/login';


  constructor(private http: HttpClient) {}


  loginUser(loginData: any): Observable<any> {

    return this.http.post<any>(this.apiUrl, loginData);

  }

  storeUserData(token: string, role: string): void {

    localStorage.setItem('authToken', token);

    localStorage.setItem('userRole', role);

  }

  getRole(): string | null {

    return localStorage.getItem('userRole');

  }

}


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

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

import { AuthService } from './auth.service'; // Import your auth service here


@Component({

  selector: 'app-login',

  templateUrl: './login.component.html',

  styleUrls: ['./login.component.css']

})

export class LoginComponent implements OnInit {

  loginForm: FormGroup;


  constructor(private fb: FormBuilder, private authService: AuthService) {}


  ngOnInit(): void {

    this.loginForm = this.fb.group({

      username: ['', Validators.required],

      password: ['', Validators.required]

    });

  }


  get username() {

    return this.loginForm.get('username');

  }


  get password() {

    return this.loginForm.get('password');

  }


  onLogin(): void {

    if (this.loginForm.valid) {

      const loginData = this.loginForm.value;

      this.authService.loginUser(loginData).subscribe(response => {

        this.authService.storeUserData(response.token, response.role);

        console.log('Login successful! Token and role saved.');

        // Redirect to the home page or dashboard

      }, error => {

        console.error('Login failed', error);

      });

    }

  }

}


Step-5 : ng g c credentials/menu --skip-tests


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

import { AuthService } from '../auth.service'; 

@Component({

  selector: 'app-menu',

  templateUrl: './menu.component.html',

  styleUrls: ['./menu.component.css']

})

export class MenuComponent implements OnInit {

  userRole: string | null = '';

  constructor(private authService: AuthService) {}

  ngOnInit(): void {

    this.userRole = this.authService.getRole();

  }

}

First, the admin will need to add book categories, as both the author and category are required for entering a book. So, the admin will have to add the category or author first, and then proceed to enter the book details. To add a category, we will perform CRUD operations on the Category, and then do the same for the Author.

However, it’s important to note that the admin should not be able to directly access menu items like Category and Author via routing. We will need to protect these routes using guards to ensure that only authorized users can access them.

Now, we will create the category form, which will require just a textbox and a submit button. This form will be designed using reactive forms. When the submit button is clicked, the category name should be posted to the API using an Angular service.


We will also create an IndexCategoryComponent, which will contain a table. Using the API, we will load all the categories into this table. In addition to the categories, we will have two buttons: one for editing the category and the other for deleting the category. When the 'Edit Category' button is clicked, the URL should include the category ID. Based on this ID, we will load the corresponding category in the EditCategoryComponent.


In the EditCategoryComponent, we will also have a textbox and a submit button. However, when we navigate to the edit form from the IndexCategoryComponent, the textbox should be pre-filled with the category details based on the ID passed in the URL.

Now, if we want to change the category, we can do so by updating the category in the textbox and then clicking the submit button. The updated category will be posted to the API through an Angular service. To achieve this, we will make a PUT request to the API to update the category.

Continue in Next Post...

© Copyright 2013 Computer Programming | All Right Reserved