Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This part of the guide is a continuation of the previous one where we have created the backend for the Book Management System. In this section, we will provide a step by step guide on how to implement the frontend side of the BMS.
When you are done with this tutorial, your BMS should look like this:
After we are done testing the backend, we can move to the frontend part where we will consume our APIs, manipulate the data and display results. In Angular, the principle of separation of concerns is prevalent. We can distinguish three main concepts: modules, components and services. We will go through each one of them as we continue building our Book Management System.
We need to generate a component for our application. In our console, navigate to the book management folder that we have created earlier. Your path should look similar to:
Once reached, we are ready to create our component. Angular allows us to generate a component with a simple command:
We only need to define our component in the module we created. Your book management system module should become the following:
Finally, we create a new file "index.ts" in the list-books folder and add the following line:
In order to display the app on the dashboard's main page, we need first to add it to the database. We have provided you with a script that allows you to perform this process in an easy fashion.
First step is to pull the script from the original repository (since most likely it is not available on your fork).
Open git bash or your preferred terminal, navigate to your backend repository and type the following commands:
Finally, run npm run createApp
and fill in the prompt with information related to your app, in this, we have done the following,
Caution: Do not forget to revert back to your master branch after creating your app.
For this part you need to navigate to the frontend directory.
To display the app on the dashboard's main page, we need add an entry to the config.json
file. You can find the file at src/assets/apps/
This is how theconfig.json
file should be.
Finally, our app is displayed in the dashboard and the icon is clickable.
In this step of this tutorial, we will create a service that will consume the API route that we have defined in the backend such that we retrieve the list of the books. We will then modify our list-book component so that the list of books is displayed.
This process is somehow a little bit similar to the backend part, we start first by creating a book model. In the "src/app/shared/models" we create a new file "book.model.ts" and we add the following code:
Also we add the following line in "index.ts" that is in "src/app/shared/models".
Now, through the console we navigate to the following path:
and we type in the console:
We now need to consume the API route that we have created in the backend. To do so, we modify the "bms.service.ts" file to the following:
We need to check to add in our index.ts that is in "src/app/shared/services".
In this part, we create a new component which will be the main page for our app. We start by checking in our console that we are in the correct directory:
We generate our component by typing in the console:
Now we need to make sure that our book management system module is updated:
Finally, in our book management folder, we create a new file "index.ts" and add the following lines:
The first step is to check our directory path. Once we made sure that we are in the smuportal-frontend, we navigate to applications folder. You can navigate through folders in the console using thecd <directory>
command.
Once you reached the path, run the command:
This will create a new folder that contains a file "book-management-system.module.ts"
We also need to modify our "applications.module.ts" which in the parent folder. We will only modify the routes. We need to define that in our applications module we have added a new application (which is the book management system), and we give the path we want and its module.
Finally, we need to make some small modifications in the box booking since we modified our applications module. We need to modify the file "logistics-reservation.module.ts" by replacing line 14 with:
In addition we need to change the file "box-list.component.ts" by replacing line 96 with:
First we have to add two new functions, namely: addBook
and addNewBook
.
addBook
is responsible for making the backend API call to add a new book. In the request body, we pass the book object that has been specified in the parameters.
addNewBook
is a private method as only the service should be able to update the list of books and no other component. It is responsible for keeping the list of books up to date.
Caution: you should only add the functions addBook and addNewBook rather than replace the entire content of bms.service.ts with the code above.
For the sake of brevity, we omit all unnecessary pieces of code.
Whenever a portion of code is omitted, it is replaced by the following indicator:// ...
As mentioned earlier, addBook
makes a POST HTTP request to the backend server. It sends in the request body the book that it received as an argument. Since HTTP calls are asynchronous, we have to wait for the response of the backend by subscribing.
If the request does not go through for whatever reason, we will get an error and in that case we simply print it to the console.
Caution: Keep in mind that this is done for demonstration purposes. In reality, all errors should be handled properly and the user should be made aware that the system is misbehaving.
On the other hand, if the request succeeds, we can safely update our list of books that we defined in the service by calling addNewBook
.
Just like we did for the creation of the book list component, we will have to navigate to the directory we want our component to be created in.
Then we generate our component bms-add-book
:
We also need to define the path of adding a book to our module.
The code to add a book is rather simple. The user is presented with a form that needs to be filled out. This form contains information about the book (title, author and ISBN) as well as a submit
button. Each filed has a corresponding ID. For instance the input field for the title of the book is identifying by bookTitle
. We will see later why we need these IDs. We also want to add some styling to improve the looks of our form.
To be able to reference a bookForm
, we first have to build a form and specify the fields that we want our form to hold.
When a form is submitted, the function onSubmit()
is called and it takes as an argument the value of the form bookForm.value
.
As a matter of fact, when a book is submitted, all we need to do is to call the service responsible for adding a book with the information that was just submitted.
In any good navigation design, the user should be able to intuitively navigate through the website. To achieve that, we have to offer the user a way through which they can access the add book component as well as exit it or go back to a previous component (book listing component).
Let us go back to the book list component that we have previously created and add a button that redirects the user to the route that we defined for our add book component.
Now, we can reach the add book component from the book listing component by simply clicking on the button "Add Book".
We also want to allow the user to go back to the book listing in case they miss-clicked or simply changed their mind.
As adding a book consists of both making a backend call to add an entry to the database and updating the view, we will have to modify our BMS service and module. We will also create a component called bms-add-book
and update previously defined components for navigability.
In this section, we will add the last feature of the BMS, which is book deletion. As we have done in earlier parts, we will need to modify the module's service, templates and components.
In this part we will define some terms and concepts that will repeatedly mention in this section. It is crucial to know what you are doing (or at least have a general idea) instead of blindly writing code (even if it works!).
A component is the main building block of an Angular application, it is composed of: an HTML template that describes what to render on the page, a TS (TypeScript) class that defines the behavior of the component and a CSS selector that defines how the component is used within a template.
To put things into perspective, here is the main page of the Book Management System:
It is divided into multiple components, where each component has its own responsibility (and it can be divided even more).
We have a navbar component, that sits above another component called BmsMainPageComponent
which itself is also containing another component, ListBooksComponent
This feature allows us to reuse parts of code systematically all over the project, like the navbar for instance, without the need of rewriting it each time.
A module is a mechanism that allows to group components, services (which we will define later on in this part), pipes, etc. It is a container for a cohesive block of code that is dedicated to a specific domain. Remember that a good design should be loosely coupled and highly cohesive! In this case, the module is the whole Book Management System.
We can export some elements from the module so that they can be accessed by other modules or keep them hidden so that they are only used internally.
Angular services are singleton object that are instantiated only once during the life cycle of an Angular application. They are used to to share business logic, data and functions across components and modules of the application.
Now these are broad definitions, as we did not want to get into detailed explanation, otherwise this guide would become fairly long and cumbersome to understand. If you are interested in learning more about these concepts, feel free to check the references and the resources section.
Angular Components Overview : https://angular.io/guide/component-overview Introduction to modules : https://angular.io/guide/architecture-modules What Is a Service in Angular and Why Should You Use it? : https://dzone.com/articles/what-is-a-service-in-angular-js-why-to-use-it
Before we start coding, let's break down the project structure of the frontend. At first glance, the number of folders might seem intimidating. However, once we explain the purpose and content of each one of them, you will be able to see the logic behind this particular way of organizing the code.
Our code mainly resides in the src/
folder.
src/
contains three sub-folders namely: app/
, assets/
, environments/
. The following is a table that explains the purpose of each folder.
APP SUPPORT FILES
PURPOSE
app/
assets/
Contains image and other asset files to be copied as-is when you build your application.
environments/
Contains build configuration options for particular target environments. By default there is an unnamed standard development environment and a production ("prod") environment. You can define additional target environment configurations.
Source: Workspace and project file structure. (2020). Angular. https://angular.io/guide/file-structure
As you have already noticed by looking at the frontend code-base, src/
is not the only folder at the root of our project. There are other folders such as dist/
and e2e/
. These come much later in the development process and are not in the scope of this tutorial. We do, however, encourage you to read more about Angular's file structure in the link above.
The aforementioned file structure is not a personal architectural decision but rather the default angular skeleton application. On top of that, we have introduced a folder called shared/
. This folder represents a module that contains sub-modules.
SharedModule
is a conventional name for anNgModule
with the components, directives, and pipes that you use everywhere in your app. This module should consist entirely ofdeclarations
, most of them exported.NgModule FAQ. (2020). Angular. https://angular.io/guide/ngmodule-faq#sharedmodule
In our implementation, the shared module contains components (breadcrumb, home-message and interceptors and user-actions), services, models and pipes. For instance, the breadcrumb component might be used in the dashboard component as well as the profile component. In other words, we want to show the breadcrumb inside the profile page and the dashboard. Since the breadcrumb is being requested by more than one component, it should be part of the shared module.
We start by defining two functions in the BMS service, deleteBook
and deleteBookByID
:
deleteBook
is responsible for communicating with the API endpoint. We pass to it the book's ISBN as a parameter and the latter will be used as the endpoint's parameter to delete the book from the database.
deleteBookByID
will delete the book from the local list that we have created so that we avoid fetching the list again and provide a better UX.
In deleteBook
we are using the HTTP Client to make a DELETE
HTTP request to the backend server through the API endpoint. Note that we are not specifying the response's type (unlike what we did when fetching the list of books), that is why the function's call type parameter is set to any
.
Once the request has been successfully made, we log the response to the console at line 14 (though this is an optional step, we are just doing so as a sanity check), then we invoke deleteBookByID
to delete the book from the local list.
Caution: Again, in an ideal setting you should properly handle errors by displaying them to your user so they would be aware if the system is not acting properly.
Coming to the deleteBookByID
function, we first create an auxiliary variable of type Book[]
where we store the subject's current value and we operate on that variable. We iterate over the array to find the book with that specific ID. Once found, we delete it from the array using the method splice
, that takes the starting index and the number of elements to be deleted (in the case it is just 1). Finally, we broadcast our new list to the subject.
We will now update the ListBooksComponent
, so that we allow the user to actually delete books from the list. What we will do first is to add some changes to the template (i.e. the HTML file) of the component and then we will modify the component's TypeScript class.
Basically, what we want to achieve is to display a red button labeled "Delete" , when clicked, will remove the row from the table and display a message confirming that indeed the book has been removed.
Go to list-books.component.html
and modify it as follow,
What we have done is that we have simply created a button inside the for
loop (so that it is created at each row) and we have bound a function deleteBook()
that takes the book's ISBN as a parameter to the click
event (if you want to read more about in Angular). What will happen, is that if the user clicks on the button, that function will be triggered.
What remains now is to add the confirmation message once the user has deleted the book. Go to the top of the file add the following code block,
If you look closely, you will notice that the message has an if
directive, and this makes perfect sens since we do not want the message to be always displayed, rather, it should be visible only after deleting, so its status would depend on the value of bookRemoved
(which is a boolean variable).
The last step is to define the functions and variables (deleteBook()
and bookRemoved
) in the component's logic.
What the deleteBook()
is actually doing, is calling the previous method that we have implemented in the Book Management System's Service that is responsible for deleting books from the list and database , and then we are changing the state of bookRemoved
to true
so that the confirmation message is displayed.
Now that our service is ready, we just need to modify our component to display the book list.
Let's start first by importing the service that we have created into our book management system module. Your new module should be similar to the following code:
Our service is imported which means that we are can use it. Let's apply this in our file "list-book.component.ts"
Let's now modify our "list-book.component.html" so that our data will be displayed in a table.
One final step is to modify our main page component. We want that our main component contains the list book component. We modify the "bms-main-page.component.html"
And we also add some styling by modifying the "bms-main-page.component.css"
After assembling all the different parts together, this is how your final code should look like:
By now, ListBooksComponent
files and BMS service should be look like this,
In this part, we have illustrated how to implement the frontend side of the Book Management System module.
Though not in detailed way, but we have covered multiple concepts such as Component Navigation, Forms Handling, Event Binding, API Communication via HTTP Client and so on. These concepts should be enough to help you implement the frontend part of your module. If you have encountered any problems, you can refer the Book Management System repositories (and ) where you can find the full code base and please make sure that you have followed the steps thoroughly.
Other than that, good luck and happy coding 🎉!
Contains the component files in which your application logic and data are defined. See details .