Book Store Application With Spring Boot And Ionic Part 2

Getting Started | Building an Application with Ionic


In this part 2 of book store application we will buid an application with Ionic framewotk

Book Store Application In this tutorial we will create a project with Spring Boot for backend and Ionic for frontend using Jpa for database. The application has Admin et User The Admin can add a category and book also he can update and delete all. The user can surfing the application find all the boos by category or search by name and show more details.


Ionic apps are created and developed primarily through the Ionic command line utility (the “CLI”), and use Cordova to build/deploy as a native app. This means we need to install a few utilities to get developing.

Installing Ionic

Ionic apps are created and developed primarily through the Ionic command-line utility. The Ionic CLI is the preferred method of installation, as it offers a wide range of dev tools and help options along the way. It is also the main tool through which to run the app and connect it to other services, such as Ionic Appflow.

Before proceeding, make sure your computer has Node.js installed.

Install the Ionic CLI with npm:


$  npm install -g @ionic/cli

Starting an App

Starting a new Ionic app is incredibly simple. From the command line, run the ionic start command and the CLI will handle the rest.


Here, myApp is the name of the project, blank is the starter template, and the project type is angular.


$  ionic start book-store side-menu

Project structure


Let's go through the files and folders of the app.

/ src

Inside of the /src directory we find our raw, uncompiled code. This is where most of the work for your Ionic app will take place.


/ app

The App folder is the largest folder because it contains all the code of our ionic app. It has all the components, modules, pages, services and styles you will use to build your app.


This is the core of the project. Let’s have a look at the structure of this folder so you get an idea where to find things and where to add your own modules to adapt this project to your particular needs.


Models

Create a folder modal in side it add a class Model.ts

src/app/modal/Modal.ts


export class Book { id: number; name: string; description: string; photo: string; writer: string; price: number; size: number; page: number; publisher: string; publishDate: any; } export class Category { id: number; name: string; expanded: boolean; } export class User { id: any; username: string; password: string; admin: boolean; }

Angular Services

Angular services are singleton objects that get instantiated only once during the lifetime of an application. They contain methods that maintain data throughout the life of an application, i.e. data does not get refreshed and is available all the time. The main objective of a service is to organize and share business logic, models, or data and functions with different components of an Angular application.


An example of when to use services would be to transfer data from one controller to another custom service.


Why Should We Use Services in Angular? The separation of concerns is the main reason why Angular services came into existence. An Angular service is a stateless object and provides some very useful functions. These functions can be invoked from any component of Angular, like Controllers, Directives, etc. This helps in dividing the web application into small, different logical units which can be reused.


Create three services in the service package

- BookService
- CategoryService
- UserService

src/app/service/book.service.ts


import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { Book } from '../modal/Modal'; @Injectable({ providedIn: 'root' }) export class BookService { private url = 'http://localhost:8080/api'; constructor(private http: HttpClient) { } addBookToCategory(book: Book, idUser: number): Observable<Book> { return this.http.post<Book>(`${this.url}/addBookToCategory/${idUser}`, book); } editBook(book: Book, id: number): Observable<Book> { return this.http.put<Book>(`${this.url}/editBook/${id}`, book); } deleteBook(id: number): Observable<Book> { return this.http.delete<Book>(`${this.url}/deleteBook/${id}`); } findBookByName(id: number): Observable<Book> { return this.http.get<Book>(`${this.url}/findBookByName/${id}`); } findBookById(id: number): Observable<Book> { return this.http.get<Book>(`${this.url}/findBookById/${id}`); } findllBooks(): Observable<Book[]> { return this.http.get<Book[]>(`${this.url}/findllBooks`); } findBooksForCategory(id: number): Observablee<Book[]> { return this.http.get<Book[]>(`${this.url}/findBooksForCategory/${id}`); } }

src/app/service/category.service.ts


import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { Category } from '../modal/Modal'; @Injectable({ providedIn: 'root' }) export class CategoryService { private url = 'http://localhost:8080/api'; constructor(private http: HttpClient) { } addCategoryToUser(category: Category, idUser: number): Observable<Category> { return this.http.post<Category>(`${this.url}/addCategoryToUser/${idUser}`, category); } editCategory(category: Category, id: number, idUser: number): Observable<Category> { return this.http.put<Category>(`${this.url}/editCategory/${id}/${idUser}`, category); } deleteCategory(id: number): Observable<Category> { return this.http.delete<Category>(`${this.url}/deleteCategory/${id}`); } findCategoryById(id: number): Observable<Category> { return this.http.get<Category>(`${this.url}/findCategoryById/${id}`); } findAllCategories(): Observable<Category[]> { return this.http.get<Category[]>(`${this.url}/findAllCategories`); } findCategoriesForUser(id: number): Observablee<Category[]> { return this.http.get<Category[]>(`${this.url}/findCategoriesForUser/${id}`); } }

src/app/service/user.service.ts


import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { Cart, Category, Shopping, User } from '../modal/Modal'; const USERNAME_KEY = 'AuthUsername'; @Injectable({ providedIn: 'root' }) export class UserService { private url = 'http://localhost:8080/api'; constructor(private http: HttpClient) { } addUser(user: User): Observable<User> { return this.http.post<User>(`${this.url}/addUser`, user); } editUser(user: User, idUser: number): Observable<User> { return this.http.put<User>(`${this.url}/editUser/${idUser}`, user); } deleteUser(idUser: number): Observable<User> { return this.http.delete<User>(`${this.url}/deleteUser/${idUser}`); } findByUsername(username: string): Observable<User> { return this.http.get<User>(`${this.url}/findByUsername/${username}`); } public saveUsername(username: string) { window.sessionStorage.removeItem(USERNAME_KEY); window.sessionStorage.setItem(USERNAME_KEY, username); } public getUsername(): string { return sessionStorage.getItem(USERNAME_KEY); } public signOut() { window.sessionStorage.clear(); } }

Create pages

Now we'll continue with the project by adding pages which are the basic buildings of an Ionic app. So let's get started. You can create pages either manually or generating them using the Ionic CLI v5 which is the recommended method. In this guide we'll look first at how to create a page generate it with the Ionic CLI, then how to add it to the project.

- add-book
- add-category
- book-details
- find-all-books
- login
- main
- menu
- serch-book

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/login

We will use these components

- login.page.ts
- login.page.html

src/app/pages/login.page.ts


import { Component, OnInit } from '@angular/core'; import { ModalController } from '@ionic/angular'; import { User } from '../modal/Model'; import { UserService } from '../service/user.service'; @Component({ selector: 'app-login', templateUrl: './login.page.html', styleUrls: ['./login.page.scss'] }) export class LoginPage implements OnInit { progressBar = false; user: User = {} as User; username: string; constructor(private userService: UserService, private modalController: ModalController) { } ngOnInit() { } onSubmit() { this.progressBar = true; this.userService.findByUsername(this.username).subscribe(user => { if(user == null) { this.userService.addUser(this.user).subscribe(user => { this.user = user; this.userService.saveUsername(this.user.username); window.location.replace('/menu/main' }) } else { this.userService.editUser(this.user, user.id).subscribe(user => { this.user = user; this.userService.saveUsername(this.user.username); window.location.replace('/menu/main') }) } }); } cancel() { this.modalController.dismiss(); } }

src/app/login.page.html


<ion-header> <ion-toolbar> <ion-buttons slot="secondary"> <ion-button fill="outline" (click)="cancel()"> <ion-icon slot="start" name="star"></ion-icon> Cancel </ion-button> </ion-buttons> </ion-toolbar> </ion-header> <ion-content> <div style="font-size: 100px; text-align: center;"> <ion-icon name="person-circle-outline"></ion-icon> </div> <ion-card> <ion-spinner name="bubbles" color="primary" class="center" *ngIf="progressBar"></ion-spinner> <ion-card-header color="danger"> <ion-card-title>Authentication </ion-card-title> <ion-card-subtitle>Please enter username and password</ion-card-subtitle> </ion-card-header> <ion-card-content> <form name="user" (ngSubmit)="onSubmit()" #formRegister="ngForm" novalidate> <ion-item> <ion-input type="text" id="username" placeholder="Enter username" name="username" [(ngModel)]="user.username" #username="ngModel" required></ion-input> </ion-item> <ion-item> <ion-input type="password" id="password" placeholder="Enter password" name="password" [(ngModel)]="user.password" #password="ngModel" required></ion-input> </ion-item> <br> <ion-button type="submit" color="primary" fill="solid" size="large" expand="block" [disabled]="username.invalid || password.invalid">Login</ion-button> </form> </ion-card-content> </ion-card> </ion-content>

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/main

We will use these components

- main.page.ts
- main.page.html
- main.page.scss

src/app/pages/main.page.ts


import { Component, OnInit } from '@angular/core'; import { ModalController } from '@ionic/angular'; import { Book, Category, User } from '../model/Model'; import { BookService } from 'src/app/service/book.service'; import { CategoryService } from 'src/app/service/category.service'; import { UserService } from 'src/app/service/user.service'; import { AddBookPage } from '../add-book/add-book.page'; import { AddCategoryPage } from '../add-category/add-category.page'; import { BookDetailsPage } from '../book-details/book-details.page'; import { LoginPage } from '../login/login.page'; @Component({ selector: 'app-main', templateUrl: './main.page.html', styleUrls: ['./main.page.scss'] }) export class HomeComponent implements OnInit { categories: Category[]; books: Book[]; user: User = {} as User; userLength = 0; showBtnAdd: boolean; showIndex =- 1; categoryLength = 0; constructor(private userService: UserService, private modalController: ModalController, private categoryService: CategoryService, private bookService: BookService) { } ngOnInit() { if (this.user != null) { this.userService.findByUsername(this.userService.getUsername()).subscribe(user => { this.user = user this.showBtnAdd = this.user.admin; }); } this.categoryService.findAllCategories().subscribe(categories => { this.categories = categories; }) } async login() { const modal = await this.modalController.create({ component: LoginPage, swipeToClose: true }); return await modal.present(); } async addCategory(idUser: number) { const modal = await this.modalController.create({ component: AddCategoryPage, swipeToClose: true, componentProps: {idUser} }); return await modal.present(); } async editCategory(idCategory: number) { const modal = await this.modalController.create({ component: AddCategoryPage, swipeToClose: true, componentProps: {idCategory} }); return await modal.present(); } async addBook(idCategory: number) { const modal = await this.modalController.create({ component: AddBookPage, swipeToClose: true, componentProps: {idCategory} }); return await modal.present(); } async editBook(idBook: number, idCategory: number) { const modal = await this.modalController.create({ component: AddBookPage, swipeToClose: true, componentProps: {idBook, idCategory} }); return await modal.present(); } async bookDetails(idBook: number) { const modal = await this.modalController.create({ component: BookDetailsPage, swipeToClose: true, componentProps: {idBook} }); return await modal.present(); } deleteCategory(id: number) { if(confirm('Are you sure')) { this.categoryService.deleteCategory(id).subscribe(() => { window.location.reload(); }); } } deleteBook(id: number) { if(confirm('Are you sure')) { this.bookService.deleteBook(id).subscribe(() => { window.location.reload(); }); } } toggle(item: any, id: number, index: any) { item.expanded = !item.expanded; this.showIndex = index; this.bookService.findBooksForCategory(id).subscribe(books => { this.books = books; this.categoryLength = books.length; }) } logout() { this.userService.signOut(); window.location.reload(); } }

src/app/pages/main.html


<ion-header> <ion-toolbar color="dark"> <ion-buttons slot="start"> <ion-menu-button></ion-menu-button> <ion-title>Main</ion-title> </ion-buttons> <ion-buttons slot="end" *ngIf="showBtnAdd" (click)="addCategory(user.id)"> <ion-button> Add category </ion-button> </ion-buttons> </ion-toolbar> </ion-header> <ion-content> <ion-button color="warning" expand="block" size="small" (click)="login()" *ngIf="!user">Please login</ion-button> <ion-text color="danger" *ngIf="user"> <h1>Welcome {{user.username}}</h1> </ion-text> <ion-item-divider></ion-item-divider> <ion-text color="dark"> <h2> Categories </h2> </ion-text> <div *ngFor="let cat of categories; let i = index" class="category-block"> <ion-row no-padding class="category-banner" id="row"> <ion-col size="8" text-left button (click)="toggle(cat, cat.id, i)" align-self-center> <label style="cursor: pointer;">{{cat.name}}</label> </ion-col> <ion-col size="2" (click)="deleteCategory(cat.id)" *ngIf="showBtnAdd"> <ion-icon name="close-outline" color="danger"></ion-icon> </ion-col> <ion-col size="2" (click)="editCategory(cat.id)" *ngIf="showBtnAdd"> <ion-icon name="create-outline" color="primary"></ion-icon> </ion-col> </ion-row> <ion-slides> <ion-slide *ngFor="let book of books"> <div *ngIf="showIndex ===i && cat.expanded" [attr.id]="'undoBtn'+i"> <ion-card> <ion-card-content> <img src="{{book.photo}}" id="img" (click)="bookDetails(book.id)"> <ion-grid> <ion-row> <ion-col> <ion-button size="small" fill="outline" color="danger"> Price = {{book.price}} $ </ion-button> </ion-col> <ion-col *ngIf="showBtnAdd"> <ion-button size="small" fill="outline" color="success" (click)="editBook(book.id, cat.id)"> Edit </ion-button> </ion-col> <ion-col *ngIf="showBtnAdd"> <ion-button size="small" fill="outline" (clcik)="deleteBook(book.id)" color="warning"> Delete </ion-button> </ion-col> </ion-row> </ion-grid> </ion-card-content> </ion-card> </div> </ion-slide> </ion-slides> <div id="addBookBtn"> <p id="errorMessage" *ngIf="showIndex ===i && cat.expanded && categoryLength == 0">No book in this category</p> <ion-button *ngIf="showIndex ===i && cat.expanded && showBtnAdd" color="primary" shape="round" fill="outline" size="small" (click)="addBook(cat.id)">Add book to {{cat.name}} </ion-button> </div> </div> </ion-content> <ion-footer class="ion-no-border" *ngIf="user"> <ion-toolbar color="danger" (click)="logout(user.id)"> <ion-title>Logout</ion-title> </ion-toolbar> </ion-footer>

src/app/pages/main.scss


.category-block { margin-bottom: 4px; } .category-banner { border-left: 10px solid #b71540; background: var(--ion-color-light); height: 40px; padding: 10px; font-weight: 500; } #errorMessage { color: #c80c0c; background: antiquewhite; padding: 10px 25px; font-weight: bold; } #row { background-color: #f8c291; } #row ion-icon { cursor: pointer; } #add-icon { font-size: 28px; cursor: pointer; margin-top: -6px; } #addBookBtn { text-align: center; } #img { height: 320px; max-height: 1320px; cursor: pointer; } h1 { text-align: center; font-weight: bold; } h2 { margin-left: 20px; } ion-toolbar { cursor: pointer; }

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/add-category

We will use these components

- add-category.page.ts
- add-category.page.html

src/app/pages/add-category.ts


import { Component, OnInit } from '@angular/core'; import { ModalController} from '@ionic/angular'; import { Category} from '../model/Model'; import { CategoryService} from 'src/app/service/category.service'; @Component({ selector: 'app-add-category', templateUrl: './add-book.category.html', styleUrls: ['./add-book.category.scss'] }) export class AddCategoryPage implements OnInit { progressBar = false; category: Category = {} as Category; idCategory: number; idUser: number; constructor(private modalController: ModalController, private categoryService: CategoryService) { } ngOnInit() { if (this.idCategory != null) { this.categoryService.findCategoryById(this.idCategory).subscribe(category => { this.category = category; }) } } addCategory() { this.progressBar = true; if (this.idCategory != null) { this.categoryService.editCategory(this.category, this.idCategory, this.idUser).subscribe(category => { this.category = category; window.location.reload(); }) } else { this.categoryService.addCategoryToUser(this.category, this.idUser).subscribe(category => { this.category = category; window.location.reload(); }) } } cancel() { this.modalController.dismiss(); } }

src/app/pages/add-category.html


<ion-header> <ion-toolbar color="warning"> <ion-buttons slot="secondary"> <ion-button fill="outline" (click)="cancel()"> <ion-icon slot="start" name="star"></ion-icon> Cancel </ion-button> </ion-buttons> </ion-toolbar> </ion-header> <ion-content> <ion-card-header> <ion-card-title>Add Category</ion-card-title> </ion-card-header> <ion-card> <ion-spinner name="bubbles" color="primary" class="center" *ngIf="progressBar"></ion-spinner> <ion-card-content> <form name="category" (ngSubmit)="addCategory()" #formRegister="ngForm" novalidate> <ion-item> <ion-input type="text" placeholder="Enter name" name="name" [(ngModel)]="category.name" #name="ngModel" required> </ion-input> </ion-item> <br> <ion-button type="submit" color="dark" fill="solid" size="large" expand="block" [disabled]="name.invalid">Save</ion-button> </form> </ion-card-content> </ion-card> </ion-content>

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/add-book

We will use these components

- add-book.page.ts
- add-book.page.html

src/app/pages/add-book.ts


import { Component, OnInit } from '@angular/core'; import { ModalController} from '@ionic/angular'; import { Book} from '../model/Model'; import { BookService} from 'src/app/service/book.service'; @Component({ selector: 'app-add-book', templateUrl: './add-book.page.html', styleUrls: ['./add-book.page.scss'] }) export class AddBookPage implements OnInit { progressBar = false; book: Book = {} as Book; idCategory: number; idBook: number; constructor(private modalController: ModalController, private bookService: BookService) { } ngOnInit() { if (this.idBook != null) { this.bookService.findBookById(this.idBook).subscribe(book => { this.book = book; }) } } addBook() { this.progressBar = true; if (this.idBook != null) { this.bookService.editBook(this.book, this.idBook, this.idCategory).subscribe(book => { this.book = book; window.location.reload(); }) } else { this.bookService.addBookToCategory(this.book, this.idCategory).subscribe(book => { this.book = book; window.location.reload(); }) } } cancel() { this.modalController.dismiss(); } }

src/app/pages/add-book.html


<ion-header> <ion-toolbar color="warning"> <ion-buttons slot="secondary"> <ion-button fill="outline" (click)="cancel()"> <ion-icon slot="start" name="star"></ion-icon> Cancel </ion-button> </ion-buttons> </ion-toolbar> </ion-header> <ion-content> <ion-card-header> <ion-card-title>Add Book</ion-card-title> </ion-card-header> <ion-card> <ion-spinner name="bubbles" color="primary" class="center" *ngIf="progressBar"></ion-spinner> <ion-card-content> <form name="book" (ngSubmit)="addBook()" #formRegister="ngForm" novalidate> <ion-item> <ion-input type="text" placeholder="Enter name" name="name" [(ngModel)]="book.name" #name="ngModel" required> </ion-input> </ion-item> <br> <ion-item> <ion-input type="text" placeholder="Enter writer" name="writer" [(ngModel)]="book.writer" #writer="ngModel" required></ion-input> </ion-item> <br> <ion-item> <ion-input type="text" placeholder="Enter description" name="description" [(ngModel)]="book.description" #description="ngModel" required></ion-input> </ion-item> <br> <ion-item> <ion-input type="number" placeholder="Enter price" name="price" [(ngModel)]="book.price" #price="ngModel" required></ion-input> </ion-item> <br> <ion-item> <ion-input type="text" placeholder="Enter publisher" name="publisher" [(ngModel)]="book.publisher" #publisher="ngModel" required></ion-input> </ion-item> <br> <ion-item> <ion-input type="text" placeholder="Enter photo" name="photo" [(ngModel)]="book.photo" #photo="ngModel" required></ion-input> </ion-item> <br> <ion-item> <ion-input type="number" placeholder="Enter size" name="size" [(ngModel)]="book.size" #size="ngModel" required> </ion-input> </ion-item> <br> <ion-item> <ion-input type="number" placeholder="Enter page" name="page" [(ngModel)]="book.page" #page="ngModel" required> </ion-input> </ion-item> <br> <ion-item> <ion-input type="text" placeholder="Enter langue" name="langue" [(ngModel)]="book.langue" #langue="ngModel" required> </ion-input> </ion-item> <br> <ion-button type="submit" color="dark" fill="solid" size="large" expand="block" [disabled]="name.invalid || writer.invalid || description.invalid || price.invalid || publisher.invalid || size.invalid || page.invalid || langue.invalid">Save</ion-button> </form> </ion-card-content> </ion-card> </ion-content>

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/book-details

We will use these components

- book-details.page.ts
- book-details.page.html

src/app/pages/book-details.ts


import { Component, OnInit } from '@angular/core'; import { ModalController} from '@ionic/angular'; import { Book} from '../model/Model'; import { BookService} from 'src/app/service/book.service'; @Component({ selector: 'app-book-details', templateUrl: './book-details.page.html', styleUrls: ['./book-details.page.scss'] }) export class BookDetailsPage implements OnInit { book: Book = {} as Book; idBook: number; constructor(private modalController: ModalController, private bookService: BookService) { } ngOnInit() { this.bookService.findBookById(this.idBook).subscribe(book => { this.book = book; }) } cancel() { this.modalController.dismiss(); } }

src/app/pages/book-details.html


<ion-header> <ion-toolbar color="warning"> <ion-buttons slot="secondary"> <ion-button fill="outline" (click)="cancel()"> <ion-icon slot="start" name="star"></ion-icon> Cancel </ion-button> </ion-buttons> </ion-toolbar> </ion-header> <ion-content> <ion-card> <ion-card-header> <ion-card-subtitle>{{book.name}}</ion-card-subtitle> <ion-card-title>{{book.writer}}</ion-card-title> </ion-card-header> <ion-card-content> <img src="{{book.photo}}"> <ion-item> <ion-label> Price {{book.price}} </ion-label> </ion-item> <ion-item> <ion-label> Size {{book.size}} </ion-label> </ion-item> <ion-item> <ion-label> Pages {{book.page}} </ion-label> </ion-item> <ion-item> <ion-label> Publisher {{book.publisher}} </ion-label> </ion-item> <ion-item> <ion-label> {{book.publishDate | date}} </ion-label> </ion-item> <ion-text color="medium"> <h5>{{book.description}}</h5> </ion-text> </ion-card-content> </ion-card> </ion-content>

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/serch-book

We will use these components

- serch-book.page.ts
- serch-book.page.html

src/app/pages/serch-book.ts


import { Component, OnInit } from '@angular/core'; import { ModalController} from '@ionic/angular'; import { Book} from '../model/Model'; import { BookService} from 'src/app/service/book.service'; @Component({ selector: 'app-serch-book', templateUrl: './serch-book.page.html', styleUrls: ['./serch-book.page.scss'] }) export class SearchBookPage implements OnInit { book: Book = {} as Book; showDiv = false; constructor(private bookService: BookService) { } ngOnInit() { } searchBook() { this.bookService.findBookByName(this.book.name).subscribe(book => { this.book = book; this.showDiv = true; }); } }

src/app/pages/serch-book.html


<ion-header> <ion-toolbar color="primary"> <ion-buttons slot="start"> <ion-menu-button></ion-menu-button> <ion-title>Main</ion-title> </ion-buttons> </ion-toolbar> </ion-header> <ion-card-content> <form name="book" (ngSubmit)="searchBook()" #formRegister="ngForm" novalidate> <ion-item> <ion-input type="text" placeholder="Enter name" name="name" [(ngModel)]="book.name" #name="ngModel" required> </ion-input> </ion-item> <br> <ion-button type="submit" color="dark" fill="solid" size="large" expand="block" [disabled]="name.invalid">Search</ion-button> <form> <ion-card *ngIf="showDiv"> <ion-card-header> <ion-card-subtitle>{{book.name}}</ion-card-subtitle> <ion-card-title>{{book.writer}}</ion-card-title> </ion-card-header> <ion-card-content> <img src="{{book.photo}}"> <ion-item> <ion-label> Price {{book.price}} </ion-label> </ion-item> <ion-item> <ion-label> Size {{book.size}} </ion-label> </ion-item> <ion-item> <ion-label> Pages {{book.page}} </ion-label> </ion-item> <ion-item> <ion-label> Publisher {{book.publisher}} </ion-label> </ion-item> <ion-item> <ion-label> {{book.publishDate | date}} </ion-label> </ion-item> <ion-text color="medium"> <h5>{{book.description}}</h5> </ion-text> </ion-card-content> </ion-card> </ion-content>

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/find-all-books

We will use these components

- find-all-books.page.ts
- find-all-books.page.html

src/app/pages/find-all-books.ts


import { Component, OnInit } from '@angular/core'; import { ModalController} from '@ionic/angular'; import { Book} from '../model/Model'; import { BookService} from 'src/app/service/book.service'; import { BookDetailsPage} from '../book-details/book-details.page'; @Component({ selector: 'app-find-all-books', templateUrl: './find-all-books.page.html', styleUrls: ['./find-all-books.page.scss'] }) export class FindAllBooksPage implements OnInit { books: Book[]; constructor(private bookService: BookService, private modalController: ModalController) { } ngOnInit() { this.bookService.findllBooks().subscribe(books => { this.books = books; }); } async bookDetails(idBook: number) { const modal = await this.modalController.create({ component: BookDetailsPage, swipeToClose: true, componentProps: {idBook} }); return await modal.present(); } }

src/app/pages/find-all-book.html


<ion-header> <ion-toolbar color="primary"> <ion-buttons slot="start"> <ion-menu-button></ion-menu-button> <ion-title>Main</ion-title> </ion-buttons> </ion-toolbar> </ion-header> <ion-card-content> <ion-card *ngFor="let book of books"> <ion-card-header> <ion-card-subtitle>{{book.description}}</ion-card-subtitle> <ion-card-title>{{book.name}}</ion-card-title> </ion-card-header> <ion-card-content> <img src="{{book.photo}}" style="cursor: pointer;" (click)="bookDetails(book.id)"> <ion-item> <ion-label> Writer {{book.writer}} </ion-label> </ion-item> <ion-item> <ion-label> Price {{book.price}} </ion-label> </ion-item> <ion-item> <ion-label> Size {{book.size}} </ion-label> </ion-item> <ion-item> <ion-label> Pages {{book.page}} </ion-label> </ion-item> <ion-item> <ion-label> Publisher {{book.publisher}} </ion-label> </ion-item> <ion-item> <ion-label> {{book.publishDate | date}} </ion-label> </ion-item> </ion-card-content> </ion-card> </ion-content>

Go ahead and open your terminal or command prompt and follow the instructions:


$  ng generate page pages/menu

We will use these components

- menu.page.ts
- menu.page.html
- menu-routing.module.ts

src/app/pages/menu-page.ts


import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-menu', templateUrl: './menu.page.html', styleUrls: ['./menu.page.css'] }) export class MenuPage implements OnInit { pages = [ { title: 'Home', url: '/menu/main', icon: 'home', open: true }, { title: 'Cool shop books', open: true, children: [ { title: 'Search book', url: '/menu/search-book', icon: 'search-circle-outline' }, { title: 'All books', url: '/menu/find-all-books', icon: 'book-outline' }, ] } ]; constructor() { } ngOnInit() { } }

src/app/pages/menu-page.html



<ion-menu contentId="content"> <ion-header> <ion-toolbar color="primary"> <ion-title>Book store</ion-title> </ion-toolbar> </ion-header> <ion-content> <div *ngFor="let p of pages"> <ion-menu-toggle *ngIf="p.url"> <ion-item [routerLink]="p.url" routerDirection="root" routerLinkActive="active"> <ion-icon [name]="p.icon" slot="start"></ion-icon> <ion-label> {{p.title}} </ion-label> </ion-item> </ion-menu-toggle> <ion-item button *ngIf="p.children?.length > 0" (click)="p.open = !p.open" [class.active-parent]="p.open" detail="false"> <ion-icon slot="start" name="arrow-forward" *ngIf="!p.open"></ion-icon> <ion-icon slot="start" name="arrow-down" *ngIf="p.open"></ion-icon> <ion-label>{{p.title}}</ion-label> </ion-item> <ion-list *ngIf="p.open"> <ion-menu-toggle> <ion-item class="sub-item" *ngFor="let sub of p.children" [routerLink]="sub.url" routerDirection="root" routerLinkActive="active"> <ion-icon [name]="sub.icon" slot="start"></ion-icon> <ion-label> {{sub.title}} </ion-label> </ion-item> </ion-menu-toggle> </ion-list> </div> </ion-content> </ion-menu> <ion-router-outlet id="content" main></ion-router-outlet>

src/app/pages/menu-routing.module.ts


import { Component, OnInit } from '@angular/core'; import { Routes, RouterModule} from '@angular/router'; import { MenuPage} from './menu.page'; const routes: Routes = [ { path: '', redirectTo: 'menu', pathMatch: 'full' }, { path: 'menu', loadChildren: () => import('./pages/menu/menu.module').then(m => m.MenuPageModule) }, { path: 'login', loadChildren: () => import('./pages/login/login.module').then(m => m.LoginPageModule) }, { path: 'add-category', loadChildren: () => import('./pages/add-category/add-category.module').then(m => m.AddCategoryPageModule) }, { path: 'add-book', loadChildren: () => import('./pages/add-book/add-book.module').then(m => m.AddBookPageModule) }, { path: 'book-details', loadChildren: () => import('./pages/book-details/book-details.module').then(m => m.BookDetailsPageModule) }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], }) export class MenuPageRoutingModule {}

Add the AppRoutingModule

In Angular, the best practice is to load and configure the router in a separate, top-level module that is dedicated to routing and imported by the root AppModule.


By convention, the module class name is AppRoutingModule and it belongs in the app-routing.module.ts in the src/app folder.


app-routing-module.ts

src/app/app-routing.module.ts


import { NgModule } from '@angular/core'; import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; const routes: Routes = [ { path: '', redirectTo: 'menu', pathMatch: 'full' }, { path: 'menu', loadChildren: () => import('./pages/menu/menu.module').then(m => m.MenuPageModule) }, { path: 'login', loadChildren: () => import('./pages/login/login.module').then(m => m.LoginPageModule) }, { path: 'add-category', loadChildren: () => import('./pages/add-category/add-category.module').then(m => m.AddCategoryPageModule) }, { path: 'add-book', loadChildren: () => import('./pages/add-book/add-book.module').then(m => m.AddBookPageModule) }, { path: 'book-details', loadChildren: () => import('./pages/book-details/book-details.module').then(m => m.BookDetailsPageModule) }, ]; @NgModule({ imports: [ RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }) ], exports: [RouterModule] }) export class AppRoutingModule { }

NgModules and JavaScript modules

The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are complementary module systems that you can use together to write your apps.


In JavaScript each file is a module and all objects defined in the file belong to that module. The module declares some objects to be public by marking them with the export key word. Other JavaScript modules use import statements to access public objects from other modules.


app-module.ts


src/app/app-module.ts


import { CUSTOM_ELEMENTS_SCHEMA, NgModule, NO_ERRORS_SCHEMA } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouteReuseStrategy } from '@angular/router'; import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; import { SplashScreen } from '@ionic-native/splash-screen/ngx'; import { StatusBar } from '@ionic-native/status-bar/ngx'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { FormsModule } from '@angular/forms'; @NgModule({ declarations: [AppComponent], entryComponents: [], imports: [ BrowserModule, IonicModule.forRoot(), AppRoutingModule, FormsModule, HttpClientModule, ], providers: [ StatusBar, SplashScreen, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } ], schemas: [ CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA ], bootstrap: [AppComponent] }) export class AppModule { }

Conclusion

Now we have an overview of Spring Boot CRUD example when building a CRUD App.

We also take a look at client-server architecture for REST API using Spring Web MVC & Spring Data JPA, as well, we ware creating an Ionic app with Angular 10 project structure for building a front-end app to make HTTP requests and consume responses.





Post a Comment

Previous Post Next Post


Follow us on facebook