Search Tutorials


Ecommerce Website - Online Book Store - Create Book Admin Module - Part 4 | JavaInUse
     
 

   
   

Ecommerce Website - Online Book Store - Create Book Admin Module - Part 4

In this tutorial series we will be developing an ecommerce website for buying books. In a previous tutorial we created the book module to view existing book details. In this tutorial we will be creating the edit book module using which we can edit existing book details.

Ecommerce Website - Online Book Store using Angular 8 + Spring Boot

Ecommerce Website - Online Book Store using Angular 8 + Spring Boot Introduction Ecommerce Website - Online Book Store - Create Menu Module Ecommerce Website - Online Book Store - Create User Admin Module - Part 1 Ecommerce Website - Online Book Store - Create User Admin Module - Part 2 Ecommerce Website - Online Book Store - Create User Admin Module - Part 3 Ecommerce Website - Online Book Store - Create Book Admin Module - Part 1 Ecommerce Website - Online Book Store - Create Book Admin Module - Part 2 Ecommerce Website - Online Book Store - Create Book Admin Module - Part 3 Ecommerce Website - Online Book Store - Create Book Admin Module - Part 4 Ecommerce Website - Online Book Store - Create Book Shopping Module

Video

This tutorial is explained in the below Youtube Video.

Spring Boot Application

We will be modifying the Spring Boot Application we had created in the previous tutorial. In the controller class add a method for updating an existing Book.
package com.javainuse.controller;

import java.io.IOException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.javainuse.db.BookRepository;
import com.javainuse.model.Book;

@RestController
@CrossOrigin(origins = "http://localhost:4200")
@RequestMapping(path = "books")
public class BookController {

	private byte[] bytes;

	@Autowired
	private BookRepository bookRepository;

	@GetMapping("/get")
	public List<Book> getBooks() {
		return bookRepository.findAll();
	}

	@PostMapping("/upload")
	public void uploadImage(@RequestParam("imageFile") MultipartFile file) throws IOException {
		this.bytes = file.getBytes();
	}

	@PostMapping("/add")
	public void createBook(@RequestBody Book book) throws IOException {
		book.setPicByte(this.bytes);
		bookRepository.save(book);
		this.bytes = null;
	}

	@PutMapping("/update")
	public void updateBook(@RequestBody Book book) {
		bookRepository.save(book);
	}

	@DeleteMapping(path = { "/{id}" })
	public Book deleteBook(@PathVariable("id") long id) {
		Book book = bookRepository.getOne(id);
		bookRepository.deleteById(id);
		return book;
	}
	
	@PutMapping("/update")
	public void updateBook(@RequestBody Book book) {
		bookRepository.save(book);
	}

}

Angular Code

We will first be modifying the view book component to add the edit button-
<div class="bookDetails">
    <h2>Book Details</h2>
    
    <table>
      <tr>
        <td>Book Id</td><td>{{book.id}}</td>
      </tr>
      <tr>
        <td>Book Name</td><td>{{book.name}}</td>
      </tr>
      <tr>
        <td>Book Author</td><td>{{book.author}}</td>
      </tr>
      <tr>
        <td>Book Price</td><td>{{book.price}}</td>
      </tr>
    </table>
    <br>
              <img src="{{book.retrievedImage}}" height="200" width="200">
  <br><br>
    
    <a class="btn btn-small btn-warning" (click)="editBook()">edit</a>   
    <a class="btn btn-small btn-danger" (click)="deleteBook()">delete</a>
    
  </div>
  
Next we will be adding the editBook function in the component-
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Book } from '../../../model/Book';
import { ActivatedRoute, Router } from '@angular/router';
import { HttpClientService } from '../../../service/http-client.service';

@Component({
  selector: 'app-viewbook',
  templateUrl: './viewbook.component.html',
  styleUrls: ['./viewbook.component.css']
})
export class ViewbookComponent implements OnInit {

  @Input()
  book: Book;
  @Output()
  bookDeletedEvent = new EventEmitter();

  constructor(private httpClientService: HttpClientService, private router: Router
  ) { }

  ngOnInit() {
  }

  deleteBook() {
    this.httpClientService.deleteBook(this.book.id).subscribe(
      (book) => {
        this.bookDeletedEvent.emit();
        this.router.navigate(['admin', 'books']);
      }
    );
  }

  editBook() {
    this.router.navigate(['admin', 'books'], { queryParams: { action: 'edit', id: this.book.id } });
  }

}
Next in the Book Component html page, previously we were showing the add book page on the right if the action parameter in the url was add. Now we will be showing the add book page if the action parameter in the url is either add or edit.
<h1>Books Admin</h1>
<a class="btn btn-primary mb-3" (click)="addBook()">Add New Book</a>
<div class="container row">
  <div class="col-md-6">
    <table class="table">
      <thead>
        <tr>
          <th>ID</th>
          <th>Book Name</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let book of books">
          <td>{{book.id}}</td>
          <td>{{book.name}}</td>
          <td>
            <button type="button" class="btn btn-primary" (click)="viewBook(book.id)">Show Details</button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
  <div class="col-md-6">
    <app-viewbook *ngIf="action === 'view'" [book]="selectedBook" (bookDeletedEvent)="refreshData()"></app-viewbook>
    <app-addbook *ngIf="action === 'edit' || action === 'add'" [book]="selectedBook" (bookAddedEvent)="refreshData()"></app-addbook>
  </div>
</div>
If we now go to the Book Details page and click on edit button, we will be navigated to the Add Books Page.

In the add books page we can see the id is appended to the url.

So if we have the id in the url we will need to update book else if in url there is no id it will be add new book. We will be adding update function in the HttpClientService-
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from '../model/User';
import { Book } from '../model/Book';


@Injectable({
  providedIn: 'root'
})
export class HttpClientService {

  constructor(private httpClient: HttpClient) {
  }

  getUsers() {
    return this.httpClient.get<User[]>('http://localhost:8080/users/get');
  }

  addUser(newUser: User) {
    return this.httpClient.post<User>('http://localhost:8080/users/add', newUser);
  }

  deleteUser(id) {
    return this.httpClient.delete<User>('http://localhost:8080/users/' + id);
  }

  getBooks() {
    return this.httpClient.get<Book[]>('http://localhost:8080/books/get');
  }

  addUploadData(selectedFile) {
    return this.httpClient.post('http://localhost:8080/books/upload', selectedFile);
  }

  addBook(newBook) {
    return this.httpClient.post<Book>('http://localhost:8080/books/add', newBook);
  }

  deleteBook(id) {
    return this.httpClient.delete<Book>('http://localhost:8080/books/' + id);
  }

  updateBook(updatedBook: Book) {
    return this.httpClient.put<Book>('http://localhost:8080/books/update', updatedBook);
  }
}
We will now modify the add book component html for editing book
<h1>{{book.id == null ? 'Add' : 'Edit'}} Book - {{book.id}}</h1>

<form>
  <label for="name">Name</label>
  <input type="text" class="form-control" id="name" placeholder="Book Name" [(ngModel)]="book.name" name="name">

  <label for="author">Author</label>
  <input type="text" class="form-control" id="author" placeholder="author" name="author" [(ngModel)]="book.author">

  <label for="author">Price</label>
  <input type="text" class="form-control" id="price" placeholder="price" name="price" [(ngModel)]="book.price">

  <div class="form-group" *ngIf="book.id == null">
    <!-- only show this field on adding a book -->
    <br>
    <input type="file" (change)="onFileChanged($event)">
    <img [src]="imgURL" height="200" width="200" *ngIf="imgURL">
  </div>
  <br><br>
  <button type="button" class="btn btn-success" (click)="saveBook()">Save Book</button>
</form>
Finally in the add book component we will be checking the book id and deciding if it is a add book call or edit book. Accordingly we will make call to the spring boot.
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
import { Book } from '../../../model/Book';
import { HttpClientService } from '../../../service/http-client.service';
import { ActivatedRoute, Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';


@Component({
  selector: 'app-addbook',
  templateUrl: './addbook.component.html',
  styleUrls: ['./addbook.component.css']
})
export class AddbookComponent implements OnInit {

  @Input()
  book: Book;

  @Output()
  bookAddedEvent = new EventEmitter();

  public selectedFile;
  imgURL: any;

  constructor(private httpClientService: HttpClientService,
    private activedRoute: ActivatedRoute,
    private router: Router,
    private httpClient: HttpClient) { }

  ngOnInit() {
  }

  public onFileChanged(event) {
    console.log(event);
    this.selectedFile = event.target.files[0];

    // Below part is used to display the selected image
    let reader = new FileReader();
    reader.readAsDataURL(event.target.files[0]);
    reader.onload = (event2) => {
      this.imgURL = reader.result;
    };

  }

  saveBook() {
    //If there is no book id then it is an add book call else it is an edit book call
    if (this.book.id == null) {

      const uploadData = new FormData();
      uploadData.append('imageFile', this.selectedFile, this.selectedFile.name);
      this.selectedFile.imageName = this.selectedFile.name;

      this.httpClient.post('http://localhost:8080/books/upload', uploadData, { observe: 'response' })
        .subscribe((response) => {
          if (response.status === 200) {
            this.httpClientService.addBook(this.book).subscribe(
              (book) => {
                this.bookAddedEvent.emit();
                this.router.navigate(['admin', 'books']);
              }
            );
            console.log('Image uploaded successfully');
          } else {
            console.log('Image not uploaded successfully');
          }
        }
        );
    } else {
      this.httpClientService.updateBook(this.book).subscribe(
        (book) => {
          this.bookAddedEvent.emit();
          this.router.navigate(['admin', 'books']);
        }
      );
    }

  }

}
We are done with all the changes. If we now click on edit button, we will be redirected to the edit page. Here will will modify the book details and click on save. If we now again go to the book details page we can see that book was edited correctly. Now if we go to localhost:4200/admin/books and select an existing book-

If we now again go to the book details page we can see that book was edited correctly.

Download Source Code

Download it -
Spring Boot + Ecommerce
Angular8 Online Book Store

See Also

Spring Boot Hello World Application- Create simple controller and jsp view using Maven Spring Boot Tutorial-Spring Data JPA Spring Boot + Simple Security Configuration Pagination using Spring Boot Simple Example Spring Boot + ActiveMQ Hello world Example Spring Boot + Swagger Example Hello World Example Spring Boot + Swagger- Understanding the various Swagger Annotations Spring Boot Main Menu Spring Boot Interview Questions