Before you start reading the main content of this post I wanted to let you know that this is the second part of a posts’ series on learning Angular, so if you are coming directly to this post you might want to check the first part where I cover some of the Angular basic concepts.
In this post I’ll cover some concepts that will help you use the properties and methods from your components classes in your components templates and also I’ll show you how to hook into different moments of the lifecycle of a component.
Data Binding
One of the reasons Angular is known for since its first version is because of the features it provides to facilitate data binding, either is one-way or two-way.
But what is data binding? Well, data binding refers to the features that allows a template to be updated automatically without having to create boilerplate code to push or remove updated data to a view whenever something changes in the JavaScript classes (components classes) and also it goes the other way around, whenever something changes in the view the data gets updated in the classes.
One-way data binding
The concept of one-way data binding means that data flows only in one direction.
Component class to Component template
This is typically when you want to use a property from a component class in a component template, look at the following example:
// File: src/app/components/data-binding-one-way1/data-binding-one-way1.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-data-binding-one-way1',
templateUrl: './data-binding-one-way1.component.html',
styleUrls: ['./data-binding-one-way1.component.scss']
})
export class DataBindingOneWay1Component implements OnInit {
public favoriteTvSeries = 'Game of Thrones';
public shouldDisplay = true;
constructor() { }
ngOnInit() {
}
}
Or check in StackBlitz.
If you take a look at the /src/app/components/data-binding-one-way1/data-binding-one-way1.component.ts
file you’ll see that there are two public properties, we added favoriteTvSeries
and shouldDisplay
and we used them in the component template located in /src/app/components/data-binding-one-way1/data-binding-one-way1.component.html
.
Thanks to Angular one-way data binding whenever the value of favoriteTvSeries
and shouldDisplay
properties change on the component class the change is going to be reflected in the component template too.
Component template to Component class
Another example of one-way data binding is when something in a view changes and it needs to be updated in the component class like in the following example:
// File: /src/app/components/data-binding-one-way2/data-binding-one-way2.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-data-binding-one-way2',
templateUrl: './data-binding-one-way2.component.html',
styleUrls: ['./data-binding-one-way2.component.scss']
})
export class DataBindingOneWay2Component implements OnInit {
public clicksTotal = 0;
constructor() { }
ngOnInit() {
}
incrementClickCounter() {
this.clicksTotal++;
}
}
Or check in Stackblitz.
In this case something in the view is being changed by a user action (clicking the button “Click Me!”) and whenever the user clicks that button we are instructing the class to increment by one the clicksTotal
property on the component class.
Two-way data binding
Two-way data binding is when data flows in two directions simultaneously, is a combination of the two previously seen concepts in one-way data binding and is typically used in forms because the data in the inputs needs to stay up to date in both sides (Class and Template).
As an example, whenever a user hits a submit button for the form we can make sure that the data the user is seeing on the inputs (Template) is the same data that we are going to be using in the Class.
// File: /src/app/components/data-binding-two-way/data-binding-two-way.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-data-binding-two-way',
templateUrl: './data-binding-two-way.component.html',
styleUrls: ['./data-binding-two-way.component.scss']
})
export class DataBindingTwoWayComponent implements OnInit {
public personName = 'Daenerys';
public personLastName = 'Targaryen';
constructor() { }
ngOnInit() {
}
getPersonNameFromClass() {
alert(this.personName);
}
getPersonLastNameFromClass() {
alert(this.personLastName);
}
}
Or check in Stackblitz.
Template Syntax
In order to decide what are the users going to see in an Angular application we use HTML with extended functionality provided by Angular.
Almost all of the normal HTML tags are valid in Angular templates excepting <script></script>
tags to prevent security risks like scripts injections and other tags like <html></html>
and <body></body>
because these tags are unusable in the context of Angular components templates.
I’ll try to cover some of the basic syntax that is used in Angular components templates but if you need a full reference you can check the resources at the end of the post.
Interpolation
Interpolation simply refers to the way we can include calculated strings within Angular templates. The syntax for interpolation is {{ }}
and we simply put the expressions we want to evaluate inside the curly braces like this:
<h1>1 plus 1 is: {{ 1 + 1 }}</h1>
In this example the 1 + 1
text is not going to be printed literally because is inside the curly braces and it will instead be evaluated as an expression that will print: 2
.
Template Expressions
Simply put, template expressions are in charge of handling dynamic values inside the templates, this means that template expressions will always produce values and after Angular calculates these values they will substitute the content of the expression in the template. Some examples are:
Template expression within HTML:
<p>Welcome {{ userName }}</p>
Output: <p>Welcome Jon</p>
Template expression inside the quotes because the square brackets in the src attribute indicates that src is an Angular property binding instead of a regular HTML attribute:
<img [src]="userPictureUrl">
Output: <img src='https://jojoscode.com/image.jpg'>
Template Statements
Simply put, template statements are JavaScript functions that responds to an event in the Angular template. These functions are normally defined in the Angular component’s class:
<button (click)="openSettingsModal()">Edit Settings</button>
In this example, whenever a user clicks in the “Edit Settings” button Angular will execute the template statement openSettingsModal() which is defined in the component’s class:
Built-in Attribute Directives
Built-in attribute directives looks like normal HTML attributes but they allow the customization of HTML elements, attributes, properties and components.
Here is an example of the NgClass attribute directive:
<p [ngClass]="isRead ? 'read' : 'unread'">A normal sentence.</p>
Built-in Structural Directives
Built-in structural directives are responsible of defining the layout of the HTML, they can decide whether or not to show an HTML element (ngIf) or create multiple copies of certain HTML (ngFor).
In this example we use the NgIf structural directive to decide which HTML section to show:
<div *ngIf="isPaid">Thanks for the payment.</div>
<div *ngIf="!isPaid">Please complete your payment.</div>
In this example we use the NgFor structural directive to iterate over a list of products:
<ul>
<li *ngFor="let product of products">{{ product.name }}</li>
</ul>
Pipes
Angular pipes simply transform or formats data from its original value to a desired output. Angular comes with some common pipes like UpperCasePipe, LowerCasePipe, CurrencyPipe, PercentPipe, DatePipe and they are ready to use in Angular templates.
Here is an example of their syntax and what they do:
// UpperCasePipe (Assuming userName is 'daenerys')
<p>Hello {{ userName | uppercase }}</p>
Output: <p>Hello Daenerys</p>
Lifecycle Hooks
Because Angular components are created, rendered and destroyed based on the actions a user is performing in an application, Angular keeps track of the lifecycle of every component.
In order to improve performance Angular allow us to hook into different key of moments in the life of a component.
There are several lifecycle hooks for Angular components and to use them you simply create a method with the name of the lifecycle hook in the component’s class. Here is an example:
// /src/app/components/profile/profile.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-profile',
templateUrl: 'profile.page.html',
styleUrls: ['profile.page.scss'],
})
export class ProfilePage {
constructor() {}
ngOnInit() {
console.log('ProfilePage initialized');
}
ngOnDestroy() {
console.log('ProfilePage destroyed');
}
}
You can check all of the lifecycle hooks Angular has built-in in the resources section at the bottom of the post.
Conclussion
In this post we covered some of the fundamentals concepts to understand Angular, we went from the different ways to use data binding to how can we modify the templates with Angular specific syntax and how can we hook into the different moments in the life of a component.
As always, any feedback is welcomed and thanks for reading 🙂