In this article we will be start a journey to learn Angular.
This Part 1 of our series to cover Angular from all different aspects, we will be building an application which will connect to an API and pull data, validate input, authenticate users and many more functionality.
You can watch the full video on YouTube:
And you get the source code from GitHub:
https://github.com/mohamadlawand087/v24-AngularPart1
In this first part we will be focusing on Angular fundamentals as well building our first component.
So what we will cover today:
- What is Angular
- Why Angular
- Anatomy of Angular application
- Ingredients
- Start Coding
As always you will find the source code in the description down below. Please like, share and subscribe if you like the video. It will really help the channel
What is Angular
Angular is a javascript framework for building client-side applications using HTML, CSS and TypeScript.
Angular in its current format has been release in 2016 and has been updated ever since. And currently we are in version 11.
It's a very popular Js framework to build client side application.
Why Angular:
- Angular makes HTML more expressive, features if conditions, loops, local variable
- Data binding, track changes and process updates from the users
- modular design, create building blocks and reuse them across the applications
- Modern, take latest features in JS it support legacy and new browsers
- Simplified API
- build for speed, faster load, rendering time
- built in support for communication with backend service
- Enhance the productivity
Anatomy of an Angular application
An Angular application is composed of a set of components as well as a services which provide functionality across these component.
What is an Component:
- Template is the html for the UI, defining a view for the component
- Class: is the associated code with the view, a class contain the properties and data elements available to use in the view, methods which perform actions in the view like clicking a button
- Metadata: provide additional information about component to Angular, it is the meta which identify the class as a component
When building a lot of component how do we define all of these component into a single application.
What is a Service:
A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well.
What is a Module:
Angular Modules, they help us organise our application into functionality blocks. Every Angular application has at least 1 module which is called the root Angular Module.
An application can contain additional modules, which can provide additional features.
Ingredients
- Visual Studio Code (https://code.visualstudio.com)
- Node (https://nodejs.org/en/download/)
Setting up the project
We need to make sure we have node installed on our machine, to verify that you have it type the following command in your terminal
npm -v
then we will need to install the Angular CLI (command line interface) which will allow us to utilise and build Angular applications
npm i -g @angular/cli
Now its time to create our own application.
ng new my-app
This will take around a minute to complete, it has asked if want to enable routing we said yes, this functionality will us to communicate between different components.
Once our setup is complete, let us run the application to see what do we get out of the box, and make sure everything has been generated successfully.
ng serve -o // open the app in default browser
the command above will also give us the ability for hot reloading, so when ever we do any change in the code. It is directly compiled and reflected in the browser for us.
Let us now discuss the folder structure of our Angular application.
- e2e: end to end testing
- node_modules: npm dependencies
- src: where code lives
- App where we are going to put all of the Angular code
- index.html: app-root is the entry point of our application (we are not really going to use it)
- Styles.css is where are going to style the application
Let us start coding
Let us create our own custom component and show it, inside our src ⇒ app folder we will create a new file called hello.component.ts this is our new simple component that we will use to do the hello world component
import { Component } from '@angular/core';
@Component({
selector: 'hello-world',
template: '<h2>{{title}}</h2>'
})
export class HelloWorldComponent {
title = 'hello world from component';
}
After adding all of the code that we need inside our component how will Angular now know about it? how are we going to display this component output.
To fix this issues we need to
- the first thing we are going to do is to add the selector "hello-world" into our app.component.html html page as this app component is the entry point to our Angular application, we will delete all of our generated code and leave the router-outlet which we will discuss later and pass the selector. When we pass the selector in the html its now called the directive which mean the custom element we created.
<hello-world></hello-world>
- Then we need to update the app.module.ts to inform Angular that we have a new component
import { HelloWorldComponent } from './hello.component';
@NgModule({
declarations: [
AppComponent,
**HelloWorldComponent**
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
Now let us start developing our application, we are going to start with a list of users and in order to make our UI nicer we will be utilising bootstrap.
We will start by installing bootstrap into our application by following these steps. Open the terminal in your project and type the following
npm install bootstrap
Now that we have installed we need to import it to our global style sheet "styles.css" .
@import url(~bootstrap/dist/css/bootstrap.min.css);
Now let us start creating our User Components by convention every feature of our application will have its own folder. For this reason we will be create a folder called users inside our app folder.
Inside the users folder will create the template for our user list component user-list.component.html once we create this file let us start building the UI
<div class="card">
<div class="card-header">
User List
</div>
<div class="card-body">
<div class="row">
<div class="col-md-2">Filter by:</div>
<div class="col-md-4">
<input type="text" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4>Filtered by:</h4>
</div>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>
Name
</th>
<th>
Email
</th>
<th>
Phone
</th>
<th>
Country
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
Now we build our component, inside our users folder will create a new file called user-list.component.ts and we add the following
import { Component } from '@angular/core'
@Component({
selector: 'pm-users',
templateUrl: './user-list.component.html'
})
export class UserListComponent {
}
Now let us update our app.module.ts so we can inform Angular about our new component.
import { UserListComponent } from './users/user-list.component';
@NgModule({
declarations: [
AppComponent,
HelloWorldComponent,
**UserListComponent**
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
The final step is to add our new component to the app.component.html
<pm-users></pm-users>
Now let us run the application using the following command
ng serve -o
Now that our application is running and we can see the changes that we have created the main structure for our components let us discuss binding and how we can utilise it to build our view.
Bindings
Bindings Coordinates communication between the component's class and its template and often involves passing data. We can provide values from the class to our template and our template will provide us with actions.
Binding happens in 2 ways
- from class ⇒ template : to display information
- from template ⇒ class : to raise events and values
Binding is always in the template
We will cover 1 way binding now which is interpolation but we will cover the rest as we go
Let us start with implementation, will start by making the title of the page dynamic will start by making the page title dynamic by adding our user-list.component.ts class the following
pageTitle: string = "User list";
and then updating the user-list.component.html to the following
<div class="card-header">
{{pageTitle}}
</div>
Directives
Custom HTML elements or attributes used to extend our HTML functionalities, we can build our own custom directives or utilise Angular built in ones.
When we have created our component and utilised it inside the app.component.html we utilised our own directives.
Built in directives: *ngIf and *ngFor
Let us start utilising the built in directive *ngIf, we are going to update our table to only show the list if there is records available. To do that let us update our class component as following:
export class UserListComponent {
pageTitle: string = "User list";
users: any[] = [
{
"userId": 1,
"fullName": "Mohamad Lawand",
"email": "mohamad@email.com",
"phone": "1231123",
"country": "lebanon"
},
{
"userId": 2,
"fullName": "Richard Feynman",
"email": "richard@email.com",
"phone": "333333",
"country": "US"
},
{
"userId": 3,
"fullName": "Neil Degrasse Tyson",
"email": "neil@email.com",
"phone": "44444444",
"country": "US"
}
]
}
and now we update our template with the following
<table class="table" *ngIf="users.length">
Now let us populate the table with the user list that we have, in order to do that we are going to be utilising the *ngFor directive which will allow us to iterate through the array that we have to display information. To do that we need update our template with the following
<tbody>
<tr *ngFor='let user of users'>
<td>{{ user.fullName }}</td>
<td>{{ user.email }}</td>
<td>{{ user.phone }}</td>
<td>{{ user.country }}</td>
</tr>
</tbody>
A component listen to users actions via event bindings, event binding will allow us to bind an event to a method in our component like a click event or hover event...
We will be updating our code to show and hide the user phone numbers based on button click event. To accomplish this we need to update the component class and the template as following.
Will start by updating our class
showNumber:boolean = false;
showPhone(): void {
this.showNumber = !this.showNumber;
};
And then our template
<div class="col-md-6">
<button (click)='showPhone()' class="btn btn-primary btn-sm">
{{showNumber ? 'Hide' : 'Show'}} Phone numbers
</button>
</div>
<!-- We update the td element in our table to the following -->
<td> <span *ngIf='showNumber'>{{ user.phone }}</span></td>
The next step is for us to enable 2 way binding by adding the filter options on our table, to do that we need to utilise the FormsModule that Angular provides, we don't have that Module in our current application so we will start by adding it. Inside our app.module.ts we need to add the following
import { FormsModule } from '@angular/forms';
imports: [
BrowserModule,
AppRoutingModule,
FormsModule
],
Then in the user-list component we need to update our class to the following:
listFilter: string = '';
And then we need to update our template with the following
<div class="col-md-4">
<!-- the ngModel is only available from the FormsModule that angular provides
Its not available anywhere else -->
<input type="text" [(ngModel)]='listFilter' />
</div>
<h4>Filtered by: {{listFilter}}</h4>
Now as we can see that our filtration is not working since haven't implement the logic in our class, to implement that logic we will need to update our component.
One of the main benefits of using TypeScript is that it is strongly typed and we can tell from what what we have wrote so far everything is strong typed except the user list it is of type any.
To fix this we need to specify a custom type which is an interface. An interface is a specification identifying a release set of properties and methods. Will start by creating the interface inside the users folder, will create a new file called user.ts and update it as the following
export interface IUser {
userId: number,
fullName: string,
email: string,
phone: number,
country: string
}
Once we added our interface we now need to update our component class to take advantage of it
// We import the interface
import { IUser } from './user'
// We update the list to take advantage of our interface
users: IUser[] = [
{
"userId": 1,
"fullName": "Mohamad Lawand",
"email": "mohamad@email.com",
"phone": 1231123,
"country": "lebanon"
},
{
"userId": 2,
"fullName": "Richard Feynman",
"email": "richard@email.com",
"phone": 333333,
"country": "US"
},
{
"userId": 3,
"fullName": "Neil Degrasse Tyson",
"email": "neil@email.com",
"phone": 44444444,
"country": "US"
}
];
Before completing the filter functionality we are going to discuss the Angular Component lifecycle and then based on that we will complete the filtration
A component has a life cycle managed by Angular
Angular create a component ⇒ Render the Component ⇒ Create and render the component children ⇒ process any changes to the component
A lifecycle hook is an interface we implement to write code, when a component lifecycle occurs. the 3 main lifecycle hooks we are going to use:
OnInit: Perform component initialisation and retrieve data. Best use to do API calls to gather data (we will cover API calls in Part 2)
OnChanges: any action after change to input properties
OnDestroy: Perform cleanup
To use a lifecycle interface we need to implement it onto our class like the following
// We need to update the import
import { Component, OnInit } from '@angular/core';
// Update our class
export class UserListComponent implements OnInit {
// Add the ngOnInit functionality
ngOnInit(): void {
console.log("Init");
}
Now that we have understood the lifecycle we need discuss 1 more thing which is the getter and a setter.
So to define a property in TypeScript there is 2 way the simple way as following
simple way
name: string = "Mohamad"; // which is an easy and fast way to initialise
advance way using getter and setting, the main reason to use this is to execute methods when these variable are get and set.
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
Now we can resume the implementation of our filtration functionality by updating our component class to the following
private _listFilter: string = '';
get listFilter(): string {
return this._listFilter;
}
set listFilter(value: string) {
this._listFilter = value;
this.filteredUsers = this.performFilter(value);
}
filteredUsers: IUser[] = [];
ngOnInit(): void {
this.listFilter = '';
};
performFilter(filterBy: string): IUser[] {
filterBy = filterBy.toLowerCase();
return this.users.filter((user: IUser) =>
user.fullName.toLowerCase().includes(filterBy));
}
finally we need to update our template to utilise the filteredUser array instead of the users list
<tr *ngFor='let user of filteredUsers'>
Thank you for reading, part 2 will be release in the upcoming week.
Top comments (2)
👏👏Nice work!
This is better than the offical documentation, and the offical documentation is alredy good. I will to study using it.