Creating an Application from Scratch using .NET Core and Angular — Part 5

In this article we are going to see how to create the SPA project using Angular.

To work in the SPA project we are going to use Visual Studio Code, but you can also use any other IDE. You can download Visual Studio Code here.

Creating the project

We are going to use the Angular CLI to create the project.

The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications.

With Angular CLI you can use the command line to work with Angular. To install Angular CLI, open the command line and execute:

npm install -g @angular/cli

This is the version that I’m using:

To create the project, access the path of your project, thought command line, open the ‘src’ folder and execute:

ng new BookStore-SPA

When asked if you would like to add Angular routing, press ‘y’, and when asked which stylesheet format would you like to use, select ‘css’.

Now inside the src folder of the project, should have those four projects:

To execute the project, open the BookStore-SPA folder trought command line and execute:

ng s

If you open your browser and access http://localhost:4200/, it will display this screen:

This is the default project that is created when we create the project using Angular CLI.

You can press CTRL + C, in the command line, and then press ‘y’ to stop the application, and execute this command to open visual studio code:

code .

Initial Configuration

First we are going to install everything we need to be working in this project. We will use the Bootstrap and the toastr, which is used to show the messages in the application. To install these components, navigate through command line to “BookStore-SPA” folder.

Install Bootstrap

We will work with the “ngx-bootstrap”. This component allows us to work easily with the bootstrap with Angular. To install it, execute the command:

npm install --save @ng-bootstrap/ng-bootstrap

In the file “app.module” we also need to add this component:

import { NgbModule } from '@ng-bootstrap/ng-bootstrap';

And in the imports we need to add the “NgbModule”:

imports: [
BrowserModule,
AppRoutingModule,
NgbModule
],

Install toastr

We are going to use the toastr (you can see more information about the toastr clicking here) to display messages in the application, for that we need to add those two packages:

npm install ngx-toastr --save
npm install @angular/animations --save

And we need to add the CSS in the “angular.json” file:

"node_modules/ngx-toastr/toastr.css"

And we need to add in the imports on the “app.module.ts”:

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ToastrModule } from 'ngx-toastr';

And include them on the imports array:

BrowserAnimationsModule,
ToastrModule.forRoot()

In this same import arrays, we also need to import and add the HttpClientModule and the FormsModule:

import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
[...]imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
FormsModule,
NgbModule,
BrowserAnimationsModule,
ToastrModule.forRoot()
],

We also need to install the localize:

ng add @angular/localize

We need to include the reference to the bootstrap.css and font-awesome.min.css, in the “index.html” file (you can add those lines below the icon’s link). This is how the file must be:

Creating the Models

Inside the “app” folder, let’s create the folder “_models” and the folder “_services”. In the models folder we will have our entities, that are the Book and the Category:

Category class:

Book class:

Creating the Services

In the services folder we will have a service class for book, another for the category and another for the confirmation dialog:

Inside the “_services” folder we are going to create the files: “confirmation-dialog.service.ts”, “book.service.ts” and “category.service.ts”.

This is the “confirmation-dialog.service.ts”:

The ConfirmationDialogComponent do not exist yet, but we are going to creat it later.

It’s a good approach to add the URL of the API in the file “environment.ts”. And then the services class can use this URL from the environment file:

export const environment = {
production: false,
baseUrl: 'https://localhost:5001/'
};

In the Category and the Book Service classes, we will have methods that execute the CRUD operations and also do searching:

  • Add
  • Update
  • Get all
  • Get by id
  • Delete
  • Search

This is the TypeScript file from the Category Service:

This is the TypeScript file from the Book Service:

We also need to add those services in the “app.module.ts”, adding the import and adding in the providers:

import { BookService } from './_services/book.service';
import { CategoryService } from './_services/category.service';
import { ConfirmationDialogService } from './_services/confirmation-dialog.service';
providers: [
BookService,
CategoryService,
ConfirmationDialogService
],

Components

A Component is basically classes that will interact with the HTML that will be displayed in the browser.

Every Angular application has at least one component, the root component that connects a component hierarchy with the page document object model (DOM). Each component defines a class that contains application data and logic, and is associated with an HTML template that defines a view to be displayed in a target environment.

When we add the decorator “@Component” in the file, means that this file is a component.

The Component Structure

A component usually has four files:

  • The TypeScript file — this file is where we add the methods and the logic of the component
  • The HTML file — this file is where we add the HTML code of the component
  • The CSS file — this file is where we add the CSS of the component
  • The Spec file — this file is where we add the unit test for the component

In the Angular official documentation you can read more about it clicking here.

Creating the Components

We will have eight components in the application:

  • Book Component — which will be used to add and edit a book
  • Book List Component — which will be used to list all the books and to filter
  • Category Component — which will be used to add and edit a category
  • Category List Component — which will be used to list all the categories and to filter
  • Home Component — which will be used to display the home page
  • Nav Component — which will be used to implement the application’s nav bar
  • Confirmation Dialog Component — which will be used to display confirmation messages
  • DatePicker Component — which will be used to set a date in an input field

In the “app” folder, create two new folders, the “books” and the “categories” folder:

The structure of the components will be like this:

We can create the components through the command line. Let’s starting creating the category component. Do to it, navigate to the categories folder in the SPA project (BookStore-SPA\src\app\categories), and let’s create the component with the command:

ng g c category

Let’s also create the list component for the categories:

ng g c category-list

Lets to the same for the books, but of course let’s create the components inside the books folder. Navigate to the books folder and create the components:

ng g c book
ng g c book-list

The other components that we need, we can create inside the folder “app”:

ng g c home
ng g c nav
ng g c confirmation-dialog

The Date Picker Component we can create manually, so for that create a new folder with the name “datepicker”, inside the “app” folder, and create two files, the “datepicker-popup.html” and the “datepicker-popup.ts”.

This is how the structure of the application must be now:

Now we have all the components that we need. So let’s start implementing them.

App Component

In the HTML file of this component, we need to add this code:

<app-nav></app-nav>
<router-outlet></router-outlet>

Nav Component

This component is used to display the navigation bar in the header of the application. On this navigation bar we will have the options to go to the home page, to the books list page and to the categories list page.

This is the code of the HTML file:

We use the “routerLink” to redirect to the defined page.

Home component

This is the code in the TypeScript file:

In the css file we can add this:

.title-home {
padding-top: 60px;
}

Confirmation Dialog Component

This component we are going to use in the confirmation messages for when the user clicks in the button to delete a record.

This is the code in the HTML file:

This is the TypeScript file:

DatePicker Component

For DatePicker we are going to use the DatePicker from the NgBootstrap, you can found more information about this component here.

This is the HTML:

This is the TypeScript file:

We have a property named “placeholder” because then when we use this component, we can set the placeholder that we want.

We also need to add this component in the file “app.module.ts”, so add the import and the component in the declarations:

import { NgbdDatepickerPopup } from './datepicker/datepicker-popup';declarations: [
[...]
NgbdDatepickerPopup
],

Category List Component

In the HTML of this component, we will have a grid with the available categories, with the options to edit or remove a category. We will also have a search field to search the categories.

This is the HTML:

This is the TypeScript file:

You can see in line 28 that we are using a debounceTime(1000) in the searchValueChanged, and this is because with that we can set a timer to this property, so when the user types something in the searching field, it will wait some seconds to do the searching, otherwise if we do not do this, for each letter the user type it would be executed a search operation.

In the CSS file we will have this:

.jumbtron {
padding-top: 60px;
}

Category Component

This component will be used to create a new category or to edit an existent category.

This is the HTML of the category component:

This is the TypeScript file:

This is the CSS:

.form {
margin: 0 auto !important;
float: none !important;
}
.jumbtron {
padding-top: 60px;
}

Book List Component

In the HTML of this component, we will have a grid with the available books, with the options to edit or remove a book. We will also have a search field to search the books.

This component is similar to the category list component, the biggest difference it’s because on this component we have more properties.

This is the HTML:

You can find a commented code in the TypeScript file, and this is just there to give an example of how you could use the searching using only the front-end if you want. This is the TypeScript file:

This is the CSS file:

.jumbtron {
padding-top: 60px;
}

Book Component

This component will be used to create a new book or to edit an existent book.

This is the HTML:

You can see that we have an “invalid-feedback” div, and this is used to display a error message to the user, for example if the user click on the field, and left it empty, it will be displayed that the field is required.

This is the TypeScript file:

This is the CSS:

.form {
margin: 0 auto !important;
float: none !important;
}
.jumbtron {
padding-top: 60px;
}

Routes

In the “app-routing.module.ts” we need to include the imports and add the routes in the variable “routes”:

import { HomeComponent } from './home/home.component';
import { BookListComponent } from './books/book-list/book-list.component';
import { BookComponent } from './books/book/book.component';
import { CategoryListComponent } from './categories/category-list/category-list.component';
import { CategoryComponent } from './categories/category/category.component';
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'books', component: BookListComponent },
{ path: 'book', component: BookComponent },
{ path: 'book/:id', component: BookComponent },
{ path: 'categories', component: CategoryListComponent },
{ path: 'category', component: CategoryComponent },
{ path: 'category/:id', component: CategoryComponent },
{ path: '**', redirectTo: 'home', pathMatch: 'full' }
];

This is how the file “app.module.ts” should be:

Back-end

We need to add one configuration in the back-end to enable CORS, otherwise, we will not be able to connect the application.

Open the API project, and go to the “Startup.cs” file. In the “ConfigureServices” method we need to add this line:

services.AddCors();

And in the “Configure” method we need to add this line:

app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

The Application

Now let’s see how is the application, navigate to the root of the BookStore-SPA project and execute the command to run the application:

ng s

To add a new category we need to open the Category list page:

And click in the button “New Category”:

Now we added a new category and we can see in the list and after we save we will be redirected to the categories list page and the message saying that the registration was successful will be displayed::

Now let’s add a new book

When we save we will be redirected to the book list page and the message saying that the registration was successful will be displayed:

And we can see now the book in the list:

Let’s add more books and than we can also use the filter:

And we can search:

We can edit and delete the record:

To edit just click in the button and will be redirected to the book component:

When we click on the delete button it will appear a confirmation dialogue:

If we click in “Ok”, it will appear the message saying that the book was deleted:

Conclusion

We have now a SPA project implemented, which allow us to execute the CRUD operation and the searching for the books and categories. We also worked with external components like the toastr that is used to display the messages, and we also implemented a DatePicker component using the NgBootstrap.

This is the link for the project in GitHub:

https://github.com/henriquesd/BookStore

.NET Full-Stack Developer | C# | .NET | .NET CORE | ASP.NET MVC | Unit Test | Angular