Angular 9 — Complete Basics Tutorial
Intended Audience and overview of the contents
This is an elaborative tutorial on Angular 9 basics. This tutorial is designed to address audience who have some basic knowledge about JavaScript. Familiarity with React or previous versions of Angular could also help.
This tutorial also assumes you have installed Angular 9 on your computer successfully. This article is thoroughly focused on explaining the basic concepts in Angular 9.
Before you proceed further, I would highly recommend you to follow this link to learn how to install Angular, create a project in Angular and serve it to the localhost. Spend some time speculating about the files and folders created in the process before following this tutorial.
This Tutorial covers:
- How are Angular apps loaded and started?
- Components in Angular.
- Databinding in Angular
- Directives in Angular (Covers only the built-in directives in Angular 9).
Advanced topics on Angular 9 will be covered in a successive article. It will be posted by July 15th 2020.
How Angular apps get loaded and started ?
Ans:
The index.html in my-first-app/src, is the only html file served by the server. `<app-root>` is one of the user-made components. The `<app-root>` is also known as the root component of the application. This application will tie together the whole application. All the files with ‘.component’ in it’s file name are part of the root app component. You can find the following contents present in the ‘.component.ts’ file.
@Component({selector: ‘app-root’,templateUrl: ‘./app.component.html’,styleUrls: [‘./app.component.css’]})
It is called the Component Decorator, if you closely observe, the selector property in the @Component Decorator is set to ‘app-root’, it is the same name tag given in ‘index.html’, this is the information Angular looks for when replacing the `<app-root>` tag inside the ‘index.html’. It replaces with the template of the component named ‘app-root’, the template is the ‘app.component.html’ file.
How is Angular triggered?
Ans:
When `ng-serve` command is executed in CLI, the CLI bundles all the javascript and typescript files to dynamically injects the `<script>` tag along with the right imports, inside the ‘index.html’ present in `my-first-app/src/`.
Getting back to the main question to be answered, once Angular is triggered and root component of the app is selected and executed, the imports present in the `<script>` tag is dynamically injected, it contains the contents of `main.ts`, present in `my-first-app/src/main.ts`.
The `main.ts` contains many imports, it also has an option to enable production environment or not. For now the main focus should be on the last few lines, i.e.
platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));
This line bootstraps (starts) the Angular application by passing the `AppModule` as a parameter to the method `bootstrapModule()`.
`AppModule` refers to one of the imports
import { AppComponent } from ‘./app.component’;
Bootstrapping `AppComponent` means Angular will go through all the files with `app.component` name given in the `my-first-app/src/app/` directory.
For Angular to know at the time of analyzing the `my-first-app/src/index.html`, to know what is `AppModule`, we export `AppModule` inside `app.module.ts`, before doing so, we bootstrap `AppComponent` inside `@NgModule`. We will get into more detail about `@NgModule` for now we can say that, this is used by Angular to get information about root app component, at the before serving `my-first-app/src/index.html`.
Angular is a JS framework, changing DOM (‘HTML’) at runtime.
Components in Angular
App component is the root component that holds the entire application together. A component in Angular is a Typescript class that helps Angular to instantiate to create objects based on the blueprint we set up in the Typescript file.
Decorators are a Typescript feature that allow you to enhance classes. It can also be used to other elements, not just classes.
Creating a Component in Angular
There are two methods of creating the component:
a. Manually.
b. Using `ng generate component` command.
a. Manually
Although this is not a hard and fast rule, it is generally a good practice to follow the following method of file structuring.
- Create an folder under `my-first-app/src/app/`, name it appropriate to the component name. Here I have considered the name of the component as `server`.
- Create a Typescript file under the created folder in the previous step, in my case, since my component name is server, my Typescript file name would be `server.component.ts`.
- Create a HTML file under the same directory as the previous file, since my component name is server, my HTML file name would be `server.component.html`.
import { Component } from ‘@angular/core’;
Imports the Component module from core library. This is used to define the Decorator inside the Typescript file.
@Component({})
This Decorator, helps Typescript understand that the `@Component` is an Angular Component, at the time of parsing it to a Javascript file. We need to pass a Javascript object in order configure the Decorator. In this configuration, we can set up some important information which can be stored as a metadata for this class defined. This metadata will tell Angular, what to do with this class.
@Component({selector: ‘app-server’,templateUrl: ‘./server.component.html’})
1. `selector` is used to create a custom HTML tag that can be used in other components.
2. `templateUrl` is used to access the files related to the component.
b.i. Using created component in Angular
Angular uses components to build webpages and Module to basically build different components together. There may be nested modules within one module, I have considered just one AppModule bundling different components together. In other words, an app module is a bundle of functionalities of an app.
This app module can be found in `my-first-app/src/app/app.module.ts`, as you can see it is also an empty as of now and it contains a Decorater, `@NgModule`.
@NgModule({declarations: [AppComponent],imports: [BrowserModule],providers: [],bootstrap: [AppComponent]})
Inside `@NgModule` we find four properties,
1. `declarations`
2. `imports`
3. `providers`
4. `bootstrap`
`bootstrap`, defines the entry point for the Angular, in order to load the app. `imports` contains, other modules that need to be included inside AppModule if the project contains multiple modules and it is also used to import other dependencies of AppModule. `declarations`, we have given AppComponent, although AppComponent may be the root component, but it is still a component and we need to mention it in `declarations`, similarly, for angular to know that we have created a server module and would like to load it, we need to mention it in `declarations`. We also need to import the component. `providers` is not exactly needed for you to know now for this tutorial as it may confuse you, my next tutorial which will have the in-depth explanation of Angular will cover providers.
@NgModule({declarations: [AppComponent,ServerComponent],imports: [BrowserModule],providers: [],bootstrap: [AppComponent]})
To import the component, we need to mention the directory where the file resides, like this,
import { ServerComponent } from ‘./server/server.component’;
The file is included without the extension, as the extension is automatically added by Webpack.
Next, once the created component is included in `my-first-app/src/app/app.module.ts`, we need to add the custom html tag created for the component in the `my-first-app/src/app/app.component.html`, in my case,
<h3>I’m in the AppComponent!</h3><hr><app-server></app-server>
b.ii. Using `ng generate component` command
In this method we need to open a new terminal, keep the terminal already running the server as is. In the new terminal, make sure it is inside your Angular project folder. In my case `my-first-app/`. Type in the command followed by the name of the component you wish to generate in my case, `ng generate component servers`.
On successful execution, you should see the following messages on your terminal,
CREATE src/app/servers/servers.component.css (0 bytes)CREATE src/app/servers/servers.component.html (22 bytes)CREATE src/app/servers/servers.component.spec.ts (635 bytes)CREATE src/app/servers/servers.component.ts (279 bytes)UPDATE src/app/app.module.ts (482 bytes)
To be on a safer side, please re-confirm if the file was created by checking if the `my-first-app/src/app/app.module.ts` was updated, just we updated the same manually in the previous manual method.
Templates in Components
Template property mentioned in the `@Component` decorator is a mandatory property.
Two ways of using template in `@Component`,
a. External file
b. Inline template.
a. External file
Previously while demonstrating, the process of creation of a Component in Angular, we used this method of including the template. In this method we include the external HTML file. Usually this method is prefered when the HTML code for template is very big.
b. Inline template
For this method we include inline styling, we can do this by including `template` in place of `templateUrl`, as follows:
b.i. Method 1:
@Component({selector: ‘app-servers’,template: ‘<app-server></app-server><app-server></app-server>’,styleUrls: [‘./servers.component.css’]})
As you can see, this method does not support line wrapping, whatever needs to be written, has to be in the same line.
b.ii. Method 2:
@Component({selector: ‘app-servers’,template: `<app-server></app-server><app-server></app-server>`,styleUrls: [‘./servers.component.css’]})
As you can see, in this method we can use multiline HTML inline script.
Inline template method, is usually used when there are fewer lines of HTML code that has to be written. Usually less than 3 lines.
Styles in Component
We modify the `my-first-app/src/app/app.component.html` file to demonstrate how basic CSS styling is carried out in the html file. We modify to center the contents of the html file.
<div class=”container”><div class=”row”><div class=”col-xs-12"><h3>I’m in the AppComponent!</h3><hr><app-servers></app-servers></div></div></div>
For the CSS styling the `my-first-app/src/app/app.component.ts` file contains the CSS required, included.
There are two methods of including the styles,
a. By including `styleUrls` property
@Component({selector: ‘app-root’,templateUrl: ‘./app.component.html’,styleUrls: [‘./app.component.css’]})
An external file(s) is imported, this is an array of external file(s) that contains CSS styling.
b. Inline styles
@Component({selector: ‘app-root’,templateUrl: ‘./app.component.html’,styles: [`h3 {color: darkblue;}`]})
The styling is done inline, usually used for styling that involves short stykle definition(s).
Selectors in Components
We can select components by three ways in Angular, namely:
a. By element
b. By attribute
c. By class
a. By elements
Inside 'app-servers.component.ts' file
@Component({selector: ‘app-servers’,template: `<app-server></app-server><app-server></app-server>`,styleUrls: [‘./servers.component.css’]})Inside 'app-servers.component.html'<! — html — ><div class=”container”><div class=”row”><div class=”col-xs-12"><h3>I’m in the AppComponent!</h3><hr><app-servers></app-servers></div></div></div>
b. By attributes
Inside 'app-servers.component.ts' file
@Component({selector: ‘[app-servers]’,template: `<app-server></app-server><app-server></app-server>`,styleUrls: [‘./servers.component.css’]})Inside 'app-servers.component.html'<! — html — ><div class=”container”><div class=”row”><div class=”col-xs-12"><h3>I’m in the AppComponent!</h3><hr><! — <app-servers></app-servers> →<div app-servers></div></div></div></div>
c. By class
Inside 'app-servers.component.ts' file
@Component({selector: ‘.app-servers’,template: `<app-server></app-server><app-server></app-server>`,styleUrls: [‘./servers.component.css’]})Inside 'app-servers.component.html' file: (This line is not part of the code)<!- -html- -><div class=”container”><div class=”row”><div class=”col-xs-12"><h3>I’m in the AppComponent!</h3><hr><! — <app-servers></app-servers> →<! — <div app-servers></div> →<div class=”app-servers”></div></div></div></div>
It is best programming practice to use components by element method.
Databinding in Angular
It is the communication of data between the TypeScript code and HTML template for a component.
There three modes of communication between the two entities:
a. Output data:
This is when there is data being transferred from TypeScript to HTML (TypeScript — → HTML)
It can be achieved using two ways:
- String Interpolation
- Property Binding
b. Input data:
This is a situation when an event is triggered as a result of user interaction with the HTML template.
(TypeScript ← — HTML)
- Event Binding
c. Two-way data binding
This is a situation where there is data transfer in both the direction
(TypeScript ←-> HTML)
a. Output data: — String Interpolation
Inside `my-first-app/src/app/server/server.component.ts` at `export class ServerComponent{ … `
we introduce two properties, as follows:
export class ServerComponent{serverId: number = 10;serverStatus: string = ‘offline’;}
Inside `my-first-app/src/app/server/server.component.html`
<p>Server with ID {{ serverId }} is {{ serverStatus }}</p>
The `{{ }}` can be used to resolve anything that can be reduced to string. However, multi-line and block expressions cannot be written within these braces.
a. Output data: — Property Binding
We bind the properties of the component to the Angular elements in DOM that are being rendered on the HTML template. This allows us to dynamically control the elements on the website.
We achieve this by first creating a property or selecting a pre-existing property from the component. One aspect to be careful is that, the property being binded with the HTML element, should produce or contain value that is accepted by the HTML element.
Please follow the example below to understand what exactly am I trying to say,
For this example, consider the `servers.component.ts` file already created in `my-first-app/src/app/servers/servers.component.ts`.
Before we add a property, we need to edit the file to remove, inline template and include `templateUrl:` in the `@Component`.
@Component({selector: ‘.app-servers’,// template: `// <app-server></app-server>// <app-server></app-server>// `,templateUrl: ‘./servers.component.html’,styleUrls: [‘./servers.component.css’]})
We move on to add a new property named `allowNewServer`.
export class ServersComponent implements OnInit {allowNewServer = false;constructor() {}ngOnInit(): void {}}
We now edit the HTML file to let Angular know that the element binded to a property.
<Button class=”btn btn-primary” [disabled]=”allowNewServer”>Add Server</Button>
Lastly we set a timeout function, to demonstrate the dynamic state change of the button after it was successfully binded with the property. To do this we need to add the javascript function under `export class ServersComponent implements OnInit { ..`.
export class ServersComponent implements OnInit {allowNewServer = false;constructor() {setTimeout(() => {this.allowNewServer = true;}, 2000);}ngOnInit(): void {}}
You will be able to notice the dynamic state change of the button from being enabled to becoming disabled after two seconds when you visit the port on which Angular is being served using the web browser.
When to use String Interpolation or Property Binding?
When we need to show an output in the template, we use String Interpolation.
When you wish to change the native property of the HTML element, directive or a component dynamically, we use Property Binding.
P.S. -> Don’t worry, I know that you are unaware of Directives. We will learn it later in the tutorial.
Never add string interpolation expression within the `” “`
b. Input Data — Event Binding
Used to bind event triggers that occur on the template to the property defined in the TypeScript file. All HTML event can be used to be binded in Angular. The event binding syntax is as follows,
export class ServersComponent implements OnInit {allowNewServer = false;setServerStatus = ‘No server was created’;constructor() {setTimeout(() => {this.allowNewServer = true;}, 2000);}onCreateServer(){this.setServerStatus = ‘Server was created’;}ngOnInit(): void {}}
After adding `onCreateServer()` method to the class `ServersComponent`, we need to bind the event in the HTML template file.
<Button class=”btn btn-primary”[disabled]=”allowNewServer”(click)=”onCreateServer()”>Add Server</Button><app-server></app-server><app-server></app-server>
Passing and using data in event binding
This section describes how to use the event binding to pass and use data.
For this example, we consider adding an HTML input feel to accept inputs from the user. We display the accepted inputs below the input field, using string interpolation.
We need to edit our HTML file in `my-first-app/src/app/servers/servers.component.html` as follows, to add a `<label>` tag, to add a label, `<input>`, to accept the input and finally `<p>` to display the text accepted from the HTML DOM:
<label>Server Name</label><input type=”text”class=”form-control”(input)=”updateServerName($event)”><p>{{ serverName }}</p>
On the TypeScript file, it is necessary to define the functiom. In this function we will assign the input from the user to a variable declared in the TypeScript. This variable is later used to display the user input on the HTML template, using DOM. The following contents need to be added iunder the class `ServerComponent` in order to let the Angular know what is the user input and how to handle it.
serverName = ‘’;updateServerName(event: Event){this.serverName = (<HTMLInputElement>event.target).value;}
The `$event` in `updateServerName($event)` is a reserved keyword used to capture the input given from the user. This is later used in the TypeScript to reference that `event` of type `Event` is used to access the data sent from the template using DOM. This is further indicated to Angular by using `<HTMLInputElement>` that the data being accessed is from a HTML Input Element.
c. Two way data binding
It is used to have a bidirectional data flow between HTML and TypeScript.
To achieve this we need to be able to use ngModel. We need to add FormsModule from @angular/forms. The FormsModule should be added to the imports [] in `my-first-app/src/app/app.module.ts`. This is done by default if you’ve created the component in a CLI project.
By using event binding and property binding together, we achieve two way data binding. In two way data binding, the two way data binding gets triggered on input event and updates the server name in our component automatically.
<input type=”text”class=”form-control”[(ngModel)]=”serverName”>
In order to see if the data flow from the Component to Template is taking place, initialize the property, `serverName`, with some value.
serverName = ‘Currently No Servername given’;
When you serve the Angular file on the desired port, you can now see that the input field is pre-populated with ‘Currently No Servername given’.
This confirms that there is dataflow from component to HTML. To confirm dataflow from Template to component, when you delete the initialzed text and write anything new, the template is updated dynamically to show the input text just below the input HTML element.
Concluding to identify all forms of data binding
We observe that,
- Event Binding to listen to the event being triggered when we click on add server.
- Property Binding to enable button after two seconds.
- Two way data binding to display a pre-populated text at the start of the app.
- String Interpolation to display the server name in a `<p>` tag.
Contents of `my-first-app/src/app/servers/servers.component.html`<label>Server Name</label><input type=”text”class=”form-control”[(ngModel)]=”serverName”><Button class=”btn btn-primary”[disabled]=”!allowNewServer”(click)=”onCreateServer()”>Add Server</Button><p>{{ setServerStatus }}</p><app-server></app-server><app-server></app-server>
Contents of `my-first-app/src/app/servers/servers.component.ts`
import { Component, OnInit } from ‘@angular/core’;@Component({selector: ‘.app-servers’,templateUrl: ‘./servers.component.html’,styleUrls: [‘./servers.component.css’]})export class ServersComponent implements OnInit {allowNewServer = false;setServerStatus = ‘No server was created’;serverName = ‘Currently No Servername given’;constructor() {setTimeout(() => {this.allowNewServer = true;}, 2000);}onCreateServer(){this.setServerStatus = ‘Server was created! Name is ‘+this.serverName;}ngOnInit(): void {}updateServerName(event: Event){this.serverName = (<HTMLInputElement>event.target).value;}}
Directives: Built-in Directives in Angular
We have been using Directives so far without our knowledge. Components are also directives with templates.
There are two types of directives:
1. Directives with templates
2. Directives without templates.
Before we move into either of them in detail. We first take a look at the built in directives.
- ngIf
- ngStyle
- ngClass
- ngFor
ngIf
It is a built-in directive used to add conditional rednering in Angular. The HTML elements are either added or removed from the DOM. They do not hide and unhide the elements.
Usage:
<p *ngIf=”serverCreated”>Server was created. Server name is {{ serverName }}</p>
`*ngIf=”serverCreated”` the `*` signifies to Angular that the following argument is a structural directive. Which means `ngIf` changes the structure of the DOM.
Contents of `my-first-app/src/app/servers/servers.component.ts`
serverCreated = false;onCreateServer(){this.serverCreated = truethis.setServerStatus = ‘Server was created! Name is ‘+this.serverName;}
Contents of `my-first-app/src/app/servers/servers.component.html`
<label>Server Name</label><! — <input type=”text”class=”form-control”(input)=”updateServerName($event)”> →<input type=”text”class=”form-control”[(ngModel)]=”serverName”><! — <p>{{ serverName }}</p> →<Button class=”btn btn-primary”[disabled]=”!allowNewServer”(click)=”onCreateServer()”>Add Server</Button><! — <p>{{ setServerStatus }}</p> →<p *ngIf=”serverCreated”>Server was created. Server name is {{ serverName }}</p><app-server></app-server><app-server></app-server>
ngIf: adding else block by using local reference
We can also add else condition to the nfIf, this helps Angular know what to do when the `if-condition` is not met.
To achieve this, we make use of local references. We will dive deeper to what local reference means in successive parts of this tutorial.
Example:
Add a local reference name `noServerCreated` is added, by writing it with `<ng-template>`, like `<ng-template #noServerCreated></ng-template>`. This specifies to Angular, what to render when inside else block. Within this ng-template tag, we write the HTML code to be rendered.
Now that we have specified what to do when the if-condition is not met, we need to ask Angular to tell Angular to execute the else-block when if-condition is not met. To do so we write the local reference within quotes that is used to specify the action for `*ngIf`.
<p *ngIf=”serverCreated; else noServerCreated”>Server was created. Server name is {{ serverName }}</p><ng-template #noServerCreated><p>No Server was created!.</p></ng-template>>
ngStyle
It is an attribute directive, used to load css styles dynamically. Interpolate javascript object into style attribute, not css class.
Example:
Code taken from the file: `my-first-app/src/app/server/server.component.html`
<p [ngStyle]=”{backgroundColor: getColor()}”>Server with ID {{ serverId }} is {{ getServerStatus()}}</p>
Code taken from the file: `my-first-app/src/app/server/server.component.ts`
import { Component } from ‘@angular/core’;@Component({selector: ‘app-server’,templateUrl: ‘./server.component.html’})export class ServerComponent{serverId: number = 10;serverStatus: string = ‘offline’;constructor (){this.serverStatus = Math.random() > 0.5 ? ‘online’:’offline’;}getServerStatus() {return this.serverStatus;}getColor(){return this.serverStatus === “online”? ‘green’:’red’;}}
ngClass
This is used to include conditional CSS on webpages. Translates object into a class attribute. It contains a JavaScript object in between the quotes, which is a key-value pair. The key is a CSS class name and the value is the condition which determines if the class should be used or not.
Example:
Code taken from the file: `my-first-app/src/app/server/server.component.html`
<p[ngStyle]=”{backgroundColor: getColor()}”[ngClass]=”{online: serverStatus === ‘online’}”>Server with ID {{ serverId }} is {{ getServerStatus()}}</p>
Code taken from the file: `my-first-app/src/app/server/server.component.ts`
This code snippet contains only the edited part of the code. The code was only edited uner `@Component`
@Component({selector: ‘app-server’,templateUrl: ‘./server.component.html’,styles:[`.online{color: white;}`]})
ngFor
It is an in-built directive, used to iterate an operation more than once. It is used as a structural directive within the target HTML element tag.
Example:
The target file being modified for this example is `my-first-app/src/app/servers/servers.component.html`.
The `<app-server>` that was repeated twice is modified to the given code below.
<app-server *ngFor=”let server of servers”></app-server>
The target file being modified for this example is `my-first-app/src/app/servers/servers.component.ts`.
A new `servers` property is added to the class `ServerComponent` it is an empty array. The new server name is pushed to the newly declared array `servers`.
servers = [‘Testserver 1’, ‘Testserver 2’];onCreateServer(){this.serverCreated = true;this.servers.push(this.serverName);this.setServerStatus = ‘Server was created! Name is ‘+this.serverName;}
Thank You! The Angular 9 Tutorial covering Advanced concepts will be uploaded by July 15th 2020.
[UPDATE]: Due to COVID -19. The Advanced tutorial for Angular 9 has been delayed by a few weeks, Sorry for the Delay. I will be posting it soon.
Credits:
I learnt Angular 9 from this wonderful Udemy course by Maximilian Schwarzmuller