Angular 9 — The Fundamentals

Vishakh Oommen Koshy
9 min readJul 23, 2020

--

Angular is a powerful responsive framework for building mobile and desktop web applications. It is a very useful skill indeed, if you are planning to transition from a backend developer to a full stack developer.
Pre-requisites : Basic knowledge of HTML, CSS, JavaScript, MVC Framework & the Document Object Model (DOM). Knowledge of TypeScript will be a plus.

Angular is a framework for building single-page client applications. We use the Angular Command Line Interface (CLI) to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment. Angular applications depend on npm packages for many features and functions. To download and install npm packages, you need an node package manager (npm).

Why Angular?

  • Bidirectional data binding : changes in the DOM, such as user choices, are also reflected in your program data and vice-versa.
    Event Binding : update application data in response to user events
    Property Binding: bind values computed from application data to HTML.
  • Cleaner code by using TypeScript
  • Better functionality out of the box : no need to use any third-party libraries to create basic functionality for your app.
  • Modular : Developers are efficiently able to divide code into modules by making use of angular components. This helps to divide work seamlessly and promotes better maintainability.
  • Maintainability : When there are new updates to angular, we just need to run the appropriate command (ng update) and give the package name. Then it will review and automatically recommend the updates to the application.
  • Angular material : a collection of ready-to-use, well-tested UI components and modules that follow Google’s Material Design principles. It contains a range of UI components, such as navigation patterns, form controls, buttons, and indicators.
  • Test Driven Development

Getting Started

  • Install Visual Studio code : One of the popular IDEs for angular based development. Works well for beginners and its themes and colors are soothing. You can download it here and install by running the below command.
    sudo dpkg -i your_visual_code_download.deb
  • Install Node.js & Node package manager (npm) : Configure node.js PPA and then install node.js and npm using the following commands.
curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -sudo apt-get install nodejs
  • Install the Angular CLI: We use CLI to create projects, generate application and library code, and perform a variety of tasks such as testing, bundling, and deployment. Install it by running the following command.
sudo npm install -g @angular/cli
Install dev kit by running the following command:
npm install --save-dev @angular-devkit/build-angular
  • Now let us go ahead and create our first angular application by running the below command.
ng new sample-appInstall the dependencies using the below command, 
npm install
  • Run your application by using the following command. If setup was successful your browser automatically loads the angular welcome page at http://localhost:4200/.
cd sample-app
ng serve --open

Building Blocks

This is how the building blocks of Angular framework work together. Ref. https://angular.io
  • Modules — provide compilation context for components. Eg. NgModule. Organizing code into functional modules promote re-usability as well as lazy loading where modules are loaded just on demand, thus minimizing size of code loaded during application startup.
  • Components : Every angular app has a root component that connects the component hierarchy with the page DOM.
    Each component is associated with an HTML template that defines a view to be displayed.
    Each component has a class containing the application data and logic. The @Component() decorator identifies the class.
    Components use services which provide specific function that can be injected into components as dependencies, making your code modular, reusable, and efficient.
  • Services : For containing data and logic that should be shared among components, we can create a service class. We use the @Injectable() decorator after the service class definition which provides the metadata that allows other providers to be injected as dependencies into your class.
  • Routing : The angular Router module lets you define navigation path among different application states and view hierarchies in your app. It maps URL-like paths to views. The router lazy loads a module on demand, if it has not already been loaded. We can associate navigation paths with our components.

The next section explains in detail how these building blocks function together.

Flow of Execution

Modules

Angular has its own modularity system called NgModules. Every Angular app has at least one NgModule class the root module, named AppModule and resides in a file named app.module.ts. This AppModule provides the bootstrap mechanism that launches the angular application. An NgModule can link components with related code (for e.g. services) to form functional units.

The execution starts with main.ts. We launch our app by bootstrapping the root NgModule from main.ts.

import { enableProdMode } from ‘@angular/core’;
import { platformBrowserDynamic } from ‘@angular/platform-browser-dynamic’;
import { AppModule } from ‘./app/app.module’;
import { environment } from ‘./environments/environment’;
if (environment.production) {enableProdMode();}platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));

NgModule is defined by a class decorated with @NgModule(). Below are the chief properties of NgModule.

  • declarations: The components, directives, and pipes that belong to this NgModule.
  • exports: The subset of declarations that should be visible and usable in the component templates of other NgModules.
  • imports: Other modules whose exported classes are needed by component templates declared in this NgModule.
  • providers: Creators of services that this NgModule contributes to the global collection of services; they become accessible in all parts of the app.
  • bootstrap: The main application view, called the root component, which hosts all other app views. Only the root NgModule should set the bootstrap property.

Here is what a sample NgModule definition app.module.ts looks like.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import { SignInComponent } from './sign-in/sign-in.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HomeComponent } from './home/home.component';
import { TokenInterceptorService } from './service/token-interceptor.service';
@NgModule({declarations: [AppComponent,SignInComponent,HomeComponent],imports: [BrowserModule,AppRoutingModule,NgbModule,HttpClientModule,FormsModule,ReactiveFormsModule,],providers: [{provide: HTTP_INTERCEPTORS, useClass: TokenInterceptorService, multi: true }],bootstrap: [AppComponent]})export class AppModule { }

Components

The @Component decorator identifies the class immediately below it as a component class and contains its metadata. The metadata for a component tells Angular where to get the major building blocks that it needs to create and present the component and its view. It associates a template with the component. The common @Component configurations are as follows:

  • selector: This is a CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML.
  • templateUrl: The module-relative address of this component's HTML template. There is also an option to provide the HTML template inline.
  • providers: An array of providers for services that the component requires.

You can create a new component by using the following command

ng generate component your-component-name

Here is an example for a component class.

import { Component} from '@angular/core';import { DataSharingService } from './service/data-sharing.service';import { AuthenticationService } from './service/authentication.service';import { Router } from '@angular/router';@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.scss']})/*** TS for header and footer component (App basic component)*/export class AppComponent {constructor(private dataSharingService: DataSharingService,public authService : AuthenticationService, private router:Router) {}ngOnInit(): void {     if(this.authService.isUserLoggedIn()){          this.authService.startSessionTimer();     }}logout(){     if(confirm('Do you wish to logout?')){          this.authService.logout();     }}}

Template: The template is just regular HTML, which also contains Angular elements giving the dynamic nature to the view based on your app’s logic and the state of app and DOM data. Your template can use data binding to coordinate the app and DOM data

Data Binding in Components : Angular supports two-way data binding. In two-way binding, a data property value flows to the input box from the component as with property binding. The user’s changes also flow back to the component as with event binding.

<!-- Angular Property Binding in HTML -->
<input [(ngModel)]="object.propertyName">
<span>{{object.propertyName}}</span>
<!-- Event Binding -->
<button (click)="onClick()">Click me!</button>

Services

Service is a class with a well defined purpose. They contain re-usable logic which can me utilized by multiple components thus making the latter lean and efficient and promoting code re-usability. Services are injected into components via dependency injection.

You can create a new service by using the following command.

ng generate service your-service-name

Below is an error handler service I have used, for handling errors while invoking web services from my angular components.

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { HttpErrorResponse } from '@angular/common/http';
import {GET_HELP_MESSAGE, SERVER_ERROR_HTTP_MESSAGE, SERVICE_UNAVAILABLE_HTTP_MESSAGE, BE_BACK_MESSAGE, BAD_GATEWAY_HTTP_MESSAGE, GATEWAY_TIMEOUT_HTTP_MESSAGE } from '../app.constants';@Injectable({providedIn: 'root'})export class ErrorHandlerService{constructor(private router : Router) { }
handleHttpErrors(error:any){if (error instanceof HttpErrorResponse) {if(error.status === 500)this.router.navigate(['error',error.status,`${SERVER_ERROR_HTTP_MESSAGE}`+`${GET_HELP_MESSAGE}`]);else if(error.status === 503)this.router.navigate(['error',error.status,`${SERVICE_UNAVAILABLE_HTTP_MESSAGE}`+`${BE_BACK_MESSAGE}`]);else if(error.status === 504)this.router.navigate(['error',error.status,`${BAD_GATEWAY_HTTP_MESSAGE}`]);else if(error.status === 503)this.router.navigate(['error',error.status,`${GATEWAY_TIMEOUT_HTTP_MESSAGE}`]);elsethis.router.navigate(['error',error.status,`${GET_HELP_MESSAGE}`]);}}}

Add the service as a parameter (shown below) in the constructor of the component where you intend to use it. When Angular creates a new instance of a component class, it determines which services or other dependencies that component needs by looking at the constructor parameter types.

constructor(private http : HttpClient, private errService :     ErrorHandlerService,private router:Router, private ds : DataSharingService) {
}

Routing

As users use the application they need to move between different views to carry out various tasks. To manage navigation from one view to another we use the Angular router. The router enables navigation by interpreting a browser URL as an instruction to change the view.

Configuring Routes

AppRoutingModule is an NgModule where you can configure routes.

  • Import the AppRoutingModule into AppModule (app.module.ts) and add it to the imports array. Angular CLI automatically does this for you if you have created the application using CLI.
  • Import RouterModule and Routes into your routing module. Angular CLI performs this step too. and sets up a Routes array for your routes and configures the imports and exports arrays for @NgModule().
  • Define your routes in your Routes array. Each route has a property path, which defines the URL path for the route and another property component, which defines the component Angular should use for the corresponding path.
  • Start using the routes in your application as follows.
<a [routerLink]="['/home']"> Home </a>
  • Route Matching Strategy :
    Router uses a first-match wins strategy when matching routes, so more specific routes should be placed above less specific routes.
    Place the wildcard route at last as it matches every URL and the Router selects it only if no other routes match first.

Here is an example for a route configuration in app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignInComponent } from './sign-in/sign-in.component';import { FamilyEventsComponent } from './family-events/family-events.component';import { HomeComponent } from './home/home.component';import { ErrorComponent } from './error/error.component';import { RouteGuardService } from './service/route-guard.service';import { RegisterComponent } from './register/register.component';import { AdminApprovalsComponent } from './admin-approvals/admin-approvals.component';import { GenealogyComponent } from './genealogy/genealogy.component';import { DirectoryComponent } from './directory/directory.component';import { GodmodeComponent } from './godmode/godmode.component';const routes: Routes = [
{
path: 'home',component: HomeComponent,},
{
path: 'login',component: SignInComponent,},{path: 'error/:errorCode/:errorMessage',component: ErrorComponent,},{path: '',component: HomeComponent,},{path: '**',component: ErrorComponent,}];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule]})export class AppRoutingModule { }

Securing Routes

  1. We may use route guards to prevent users from navigating to parts of an app without authorization. Firstly create a service for your guard which implements the guard you want to use. Angular contains the following guard interfaces :
  • CanActivate to mediate navigation to a route.
  • CanActivateChild to mediate navigation to a child route.
  • CanDeactivate to mediate navigation away from the current route.
  • Resolve to perform route data retrieval before route activation.
  • CanLoad to mediate navigation to a feature module loaded asynchronously.

In the below code, we secure a route based on authentication. Hence we choose the CanActivate route guard.

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthenticationService } from './authentication.service';
@Injectable({
providedIn: 'root'
})
export class RouteGuardService implements CanActivate{constructor(private authService : AuthenticationService, private router : Router) { }canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {if(this.authService.isUserLoggedIn()){
return true;
}
else{
// re-directing user to the login component
this.router.navigate(['login']);
return false;
}
}}

2. Next, in your routing module app-routing.module.ts use the appropriate property in your routes configuration. In the below code snippet, canActivate tells the router to mediate navigation to this particular route by using the RouteGuardService we created in the previous step.

{ path: 'directory',component: DirectoryComponent,canActivate : [RouteGuardService]}

Thank you for your valuable time. Hope you now have a good understanding about the fundamentals of Angular framework. Good Luck folks!

Keep an eye on my story space for upcoming articles on the usage of more advanced features of the Angular framework.

--

--

Vishakh Oommen Koshy

Developer 👨🏻‍💻 Writer 📝 Wanderer 👣🌏 | ♥️ Cars 🚘 Nature 🌳 Gardening 🌿& Cats 🐈 | Tech💡 WebApp, Security, Java, SpringBoot, Hibernate, NoSQL, AWS, Cloud