Animations on Scroll – Made Easy!

Have you ever wanted to rapidly increase the usability of your site or the application? It’s going to be an undoubted yes because that’s what every developer dreams of making it – right? There are various ways that we can experiment with our sites, some work better than others and some require more time to get working! Even if you’ve found the user experience challenging, you can make it better, and I’ll show you how!

Anything that doesn’t jump off the page as interesting, exciting, funny, or relevant is liable to get slashed user experience. Most people will at least have a glance throughout the page just by scrolling since they’re not intended to read the entire page content at first. So, scrolls are one of the perfect places to grab the attention of the users and to enhance the usability of them. If you make scrolling, an exciting and an addictive one, you can boost the user’s experience while being able to brand your site and keep them engaged!

Let’s jump right into the ways in which we can implement the animations on scrolling. Animation on Scroll (AOS) is a perfect library that makes animations really easy and fascinating while scrolling the page. I recommend taking a look at the AOS official docs which has ready to use templates with several use cases. So the idea of this blog is to cover the initial setup for implementing the scroll animations in your project which is not explained in their doc.

I’ve listed the initial setup for Angular, Vue.js and React projects since they’re the most popular amongst the biggest front end frameworks. Let’s get them done one by one. But in general, we need to add AOS to our dependencies.

Run npm install aos --save

Either run npm i or add the CDN sources for CSS and JS in your index.html file.

CSS: <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">

JS: <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>

Next comes the initialization part of AOS. A piece of common information on initialization of AOS is, we always need to import and init them in the app or any other parent level component of which we need to do animations. This is due to the fact that AOS has observers in it, so whenever a new element appears in DOM, it is supposed to animate them properly.

  1. Initialize AOS in Angular

    We need to initialize the AOS in your app.component.ts as follows,
    a. Import the AOS library in your component
import * as AOS from 'aos';

b. We need to initialize the AOS library during the initialization of your component. So let’s initialize AOS on the ngOnInit lifecycle hook.

AOS.init();
  1.   Initialize AOS in Vue.js

a. Import the AOS library in main.js file.

import * as AOS from 'aos';
import 'aos/dist/aos.css';

b. We need to initialize the AOS library during the creation of your component. So let’s initialize AOS on the Created() lifecycle hook. Add the following snippet in the new Vue portion of the main.js file.

new Vue({
   created () {
       AOS.init()
   },   
   router,
   store: Store,
   render: h => h(App)
}).$mount('#app');
  1. Initialize AOS in React

The steps are apparent now so let’s just have a glance at the following code snippet to understand the flow in React.

import AOS from 'aos';
import 'aos/dist/aos.css';
.
.
.
 componentDidMount(){
   AOS.init({
     duration : 2000
   })
 }

Initialization is now complete! Try adding data-aos=”fade-up” to any of your HTML element and admire the animations on scrolling. Refer the AOS docs for more customized scroll animations.

Reference

  1. https://michalsnik.github.io/aos/

Reactive Forms (Angular)

We all know that Angular Application is a reactive system. We have two categories of form structures in Angular:

  1. Reactive Forms
  2. Template Driven Forms.

In template driven forms, the template directives are used. Whereas in reactive forms, we could build our own representation of the form in the components. Thus, we could always opt for Reactive Forms.

Let’s begin by knowing the terminologies of reactive forms.

  • formControl
  • formGroup
  • formArray
  • controlValueAccessor

In this blog, we are going to look through formControls and formGroup.

Before beginning, do not forget to import the module (ReactiveFormsModule) and import the classes (FormControl, FormGroup, FormBuilder, Validators)

Imagine you have a form with the following fields:

  1. Name
  2. Age
  3. School
  4. Class
  5. Rank

So here, each field will be having different data types (such as alphabets, numbers, etc). Thus, in reactive forms, validating the fields become very easy using the built-in properties. Also, it is very easy for us to group the individual forms and make the necessary changes.

Let’s start with formControl:
Each field is recognized using the formControls for validation. Thus, we will be setting formControl for each field. Also, default values to the fields can also be set up initially.

Illustration:
In .html file, add:

<input type="text" [formControl]="name">

In .ts file, add:

name = new FormControl('any default values');

And then we go for formGroup:
These individual form controls can be grouped together for better handling of validation stuff and named as formGroup.

Illustration:
Let the HTML file remain the same.
In .ts file, add:

formGroupVariable = new FormGroup({
name = new FormControl('Smith Katana'),
age: new FormControl(12),
});

Now using the formGroupVariable, several validations, customizations can be done using the inbuilt methods. Following are some of them:

Illustration:
In .ts file, add :

name = new FormControl('any default values', {validators: Validators.required, updateOn: 'blur'});

Here, in the second parameter, we could use the Validators Object for validations. Refer the following link for Validators API reference:
https://angular.io/api/forms/Validators

Also updateOn key will intimate the validators to validate only after every blur to avoid validations for every keystroke.

We could also add our own customized method validator by adding the method instead of Validator object as follows:

Illustration:

In .ts file, add :

name = new FormControl('any default values',validatorMethod);

function validatorMethod(name: FormControl) {
//custom validations
}

Note* This method will be called for every keystroke

If you want to have a validation like to submit the form if any of the validations have been passed and it is not necessary that all the fields should be passed. But how do we do that?

formGroupVariable.patchValue('name', { onlySelf: true });

….Simple right?

To enable or disable the form use,

formGroupVariable.enable() && formGroupVariable.disable()

And also to disable a particular form control initially we could use the disabled attribute,

Illustration:

name: new FormControl({ disabled: true, value: null })

Reference Links:

Lint Driven Development

It is no wonder that “Lint Driven Development – LDD” is one of the most essential development approach that every developer should follow up! It is an integral part of every developer’s toolbox! If you could agree my statement, then you’re already on the track of super cool development. If not, then I can get you a step further towards that through this blog.

What is linting?

You write code. Probably a lot of code. And you make mistakes. Probably a lot of mistakes. Sometimes your mistake is a real bug that can be fixed. Sometimes it’s just an unclear coding style which may seem trivial at first but they become patently important as the codebase grows and as more people stick their hands in it. You can’t always focus on fixing this inevitable mistakes that you do! Isn’t it? Because, there is probably no practical way to make it impossible to write sloppy and unclear code, but it is fascinating to consider how tooling has evolved to make it harder. One fine tooling is “Linters” which understands you and your code.

Linter is part of the style guide. It’s a small piece of software that automatically checks if your code has any stylistic or potential errors and meets the predefined code convention rules. You don’t have to manually go through the code base to check style and any errors. Linting helps us in two ways. First, it looks for code that will potentially break. Second, it provides a style guide for the development team to follow.

Why Linting is Important?

Some great movies involves compelling stories, and colorful screenplays that are easy to watch and understand. From that aspect, the job of a developer is similar to that of the movie director, since the code has to be easy to read and comprehensive. I know it’s pretty hard to focus on code quality when you’re under pressure to meet the next deadline, but if you’re thinking long term, you definitely need to write code that’s readable and maintainable.

In addition to its readability and maintainability there lies an important third reason which is lower technical debt which allows speeding up long term software development since it can be reused without involving any future developer’s time to work on fixing the old bugs and styling the code.

How Linters prevent our problems?

Linting tools throws warnings about certain types of code that can lead to common problems. Some are quite major. As a Javascript Engineer, I’ll list down some major problems in JS code and how linters could prevent those problems!

Problem #1
Most of us have got this one common question in our mind that our code works in development but why not in production? We all knew that most modern web stacks support minification, but neither the minifiers nor the browser tell us when are we missing semicolons. But a missing semicolon can break minified javascript and so it stops in production. So Linters notify you about the missing semicolons, braces, etc..

Problem #2:

Have you ever created a variable called “id” or “name” or “value”? Yeah, so has every other developer in history, and people who work on the same codebase as you is not an exception. And if someone forgets to declare all their variables with var, as they can overwrite each other unexpectedly. The scope of the variables is gone as well as your code.

You don’t always need to rely on your reviewers to find mistakes in your code and in some cases it takes too much of your reviewer’s time to find some sloppy mistakes or even they might miss it completely. Linting your JS can prevent potential XSS security holes, readability problems, and many more!

Linting Tools

Linters comes with a lot of tools that are capable of finding stylistic errors and sloppy mistakes in every technology that we use. Among many JS linters, ESLint seems to be the best available linter as it is completely plug-able, every single rule is a plugin and we can add more rules at run-time. It gives concise output, and also includes the rule name by default so it’s always easy to know which rules are causing the errors. We also have Linters for most languages like TS, CSS, HTML, Python, etc..

There are different means by which one can use linting tools to improve the code quality. To mention a few,

Linting manually, in the browser

Copy and Paste your code into JSHint or CSSLint or HTMLHint or any other static code analysis tool to check for some interesting lint errors. This might be the quickest way to get started with linting.

Linting from your code editor

Many code editors have support for configurable linting, such as VSCode. Here is the guide to configure Linters in VSCode. It has many extensions for all of the linters above. Grab one and have it check your code automatically which is really great since you’re already in your editor, where you can clean your code up simultaneously while you write it.

Linting from the command line

If you’re using a command line tool like Npm, you’re ahead of the curve. Just install a linter of your choice and follow some commands to get notified of your errors in code.

Linting as part of the build process

This is the best way to ensure that these types of problems never see the light of day. I recommend adding a flag to the ng serve and the ng build commands that automatically runs ng lint before each build and causes a build failure on any linter rule violation.

Even if you set up a linter, it might warn you against invalid code but it cannot stop you from pushing this code to the repo. This is where Git pre-commit hook comes into the picture. It’ll restrict the developer from committing the code if it doesn’t pass the rules available in .git/hooks. For information about Git Hooks, please visit here.

It is NoteWorthy!

I recommend turning off most of your linter’s settings when you start using it, so that you have a minimal set of errors to start with. Consider the ones it throws out, learn what they mean and then fix them. Later, re-enable another setting and repeat until you understand all the rules. I understand, it takes some time to understand everything and to get them fixed up. Let me copy out some words from Bruce Lee.

“I fear not the man who has practiced 10,000 kicks once,

         but I fear the man who has practiced one kick 10,000 times.”

– Bruce Lee

Software development is pretty much always slower than anyone wants it to be. It takes time. Sometimes you just have to be patient enough to turn out the code you need to write. No matter how long you’ve been in this field, you should keep practicing the craft of coding.

Conclusion

Linting is a vital part of our workflow, and will definitely help us improve our skills. If you were not using linting, I hope this blog convinced you a bit to configure lint to your code. I think Linting is one of the traits that makes a good developer! What do you think makes a great developer? Love to hear from you!

Angular Lazy Loading

In this blog, we will be learning about lazy loading in angular. The main concept of lazy loading is that don’t load something which you don’t need. Lazy loading is a useful technique for reducing the size of the bundle when the app loads initially which improves the app loads time thus improving the user experience. It’s also easy to have features loaded only when the user navigates to their routes for the first time.

Main steps to set up lazy loading

  1. Create a feature module.
  2. Use loadChildren in the main routing module.
  3. Create a routing module for feature module.

Create a feature module

In order to use lazy loading, we need submodules in our applications often called a feature module. Assuming that you have an Angular CLI project, let’s create a feature module using the following command.

Create lazy loading module

Note: Don’t load the feature module in your main module.

Now let’s create two components inside the lazyLoading module using the following command.

Create lazy loading component

Use loadChildren in the main routing module

Now let’s load the feature module in our main routing module (app-routing.module.ts). We need to use loadChildren() method to lazy load the feature module.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  {
    path:'lazyLoading',
    loadChildren:
      './lazy-loading/lazy-loading.module#LazyLoadingModule'
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

export class AppRoutingModule { }

 

The loadChildren() method takes the path to the module, then # followed by the module’s class name.

Create a routing module for a feature module

Now let’s configure routes in the routing module for the components under the feature module.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { OneComponent } from './one/one.component';
import { TwoComponent } from './two/two.component';

const routes: Routes = [
{ path: '', component: OneComponent },
{ path: 'two', component: TwoComponent },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})

export class LazyLoadingRoutingModule { }

 

In the feature routing module include the routes with RouterModule’s forChild() method instead of the forRoot() method.

Lazy loading has been configured successfully now LazyLoadingModule will load only when the user navigates to “/lazyLoading”.

Preloading Strategy

When we run the application only the main modules are loaded all the other modules are lazy loaded. In this case, the lazily loaded modules load only when the user navigates to the feature module. Since the module is lazy loaded we have to wait for it to be loaded to overcome this we can use preload strategy.

To use preloading strategy we have to add preloadingStrategt in our app-routing.module.ts as shown below.

import { NgModule } from '@angular/core';
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
const routes: Routes = [
 { path: '', redirectTo: 'home', pathMatch: 'full' },
 { 
  path: 'lazyLoading', 
  loadChildren:
    './lazy-loading/lazy-loading.module#LazyLoadingModule' 
 }
];
@NgModule({
  imports: [RouterModule.forRoot(routes, {
    preloadingStrategy: PreloadAllModules,
  }
)],
exports: [RouterModule]
})
export class AppRoutingModule { }

The two subclasses in preloadingStrategy are.

  • NoPreloading: Default strategy which provides no preloading.
  • PreloadAllModules: Preloads all the lazy loaded modules.

By using PreloadAllModules we can load the modules which are required on the initial load of an application. All the other lazy loaded modules are loaded asynchronously right after the initial load of the application is done.

Another strategy is to preload the modules which are required and some other module with a delay. The method to use this is to add the data object to the route config as shown below.

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { 
    path: 'lazyLoading', 
    loadChildren: './lazy-loading/lazy-loading.module#LazyLoadingModule',
    data: { preload: true, delay: false }, 
  }
];

 

Reference:

 

Angular Flex-Layout

Flex layout is a package made for angular to use CSS flexbox features. The flex layout is used to display the elements within the flexbox container to be automatically arranged based on the parent container. Flex layout is used for building a layout structure. In this blog, we will be learning how to use angular flex layout module and its features.

Installation

Install the flex layout package with npm/yarn in your angular project.

$ npm i @angular/flex-layout

And add FlexLayoutModule into your AppModule.

Flex Layout

Let’s get started with flex layout features and how to use it and their properties.

  1. fxFlex

The fxFlex should be used on the element within the flexbox container. The fxFlex is used to resize the element based on the parent container. The fxFlex supports two usage long-form and short-form.

  • Long-form 
<div fxFlex="<grow> <shrink> <basis>"></div>
  • Short-form 
 <div fxFlex="<basis>"></div>

The flex basis value can be percentages, pixels, em, vm, vh, calcs.

Example:

<div fxFlex="20"> … </div>
  1. fxLayout

The fxLayout is used to specify the direction of the elements inside the flexbox container. Shown below are the property values of fxLayout.

  • row – Default value, the elements are displayed horizontally, as a row.
  • row-reverse – Same as the row, but in reverse order.
  • column – The elements are displayed vertically, as a column.
  • column-reverse – Same as the column, but in reverse order.
  • fxLayout + wrap – Specifies that the elements will wrap if necessary.

Note: when using the wrap, must first specify the layout direction.

Example:

<div fxLayout="row"> … </div>

<div fxLayout="row wrap"> … </div>
  1. fxLayoutGap

The fxLayout is used to specify the margin gaps on elements within the flexbox container. Shown below are the default mode of fxLayout.

  • margin-right is used when the flexbox container flex direction is a row.
  • margin-bottom is used when the flexbox container flex direction is a column.

Note: The last child element will not have the margin gap only the inside gap are specified.

Example:

<div fxLayoutGap="20px"> … </div>
  1. fxLayoutAlign

The fxLayoutAlign is used to align the elements inside a flexbox container. Shown below are the property values of fxLayoutAlign.

  • strat or flex-start – Default value, the elements are positioned at the beginning of the container.
  • end or flex-end – The elements are positioned at the end of the container.
  • center – The elements are positioned at the center of the container.
  • space-around – The elements are positioned with space before, between and after the lines.
  • space-between – The elements are positioned with space between the lines.
  • space-evenly – The elements have equal space around them.

Example:

 <div fxLayoutAlign="space-between center"> … </div>
  1. fxFlexOffset

This should be used on the element within the flexbox container. This is used to specify the margin-left to the elements within the flexbox container.

Example:

<div fxFlexOffset="20px"> … </div>
  1. fxFlexOrder

This should be used on the element within the flexbox container. This is used to specify the order for the elements inside the flexbox container.

Example:

 <div fxFlexOrder="2"> … </div>
  1. fxFlexFill

The fxFlexFill is used to maximizes the height and the width of the elements inside the flexbox container.

Example:

<div fxFlexFill> … </div>
  1. fxShow and fxHide

The fxShow and fxHide is used to show/hide the element based on the value passed to it.

Example:

<div fxHide="true"> … </div>

Responsive Layouts

The responsive layouts are used to apply different layout styles for different viewport sizes and display devices.  This can be used by combining breakpoints with fxLayout features. Some of the breakpoints are xs, sm, md, lg, xl for more reference responsive layouts.

Example:

<div fxHide.xs="true"> … </div>

Reference:

Materialise your Angular App

As much as I love Angular, I also recognize that there are a few things that could make your Angular App look even more stunning without much effort! So, let’s go ahead and change your life in about 5 minutes by getting productive with Material Design using Angular Material in your Angular CLI app.

So, What Exactly is Angular Material?

Angular Material Design is a design language for web and mobile apps which was developed by Google in 2014. Material Design makes it easy for developers to customize their UI while still keeping a good-looking app interface that users are comfortable with and also you’ll get a well-organized format along with the flexibility to express your brand and style. For an example of Material Design, check out Airbnb, Gmail, and Houzz. These apps make the best use of Material Design to fit its many features into the limited mobile device. Going through the official Material design documentation is quite an experience. I recommend taking a look at the docs, but I will summarize it here.

Setup the Environment for Angular

To work with Angular, you will need Node.js and Angular CLI (Command Line Interface) installed in your development environment. Proceeding further, you can use the following command to set up a new Angular project.

ng new angular-material-app

Step 1: Install Angular Material and Cdk

Head over to your terminal, navigate inside your created Angular front-end application and then run the following commands to install Angular Material 6 and Angular 6 CDK.

npm install --save @angular/material @angular/cdk

Step 2: Install Angular Animations

In order to add enable support for animations in your Angular 6 front-end application, head back to your terminal and run the following command to install the Angular animations module and import the BrowserAnimationsModule and add it to the list of imports.

npm install --save @angular/animations

Step 3: Angular Material Theme

Angular Material comes prepackaged with several pre-built theme CSS files. To configure the basic theme, open the src/styles.css file and import any one of the available themes in Material Themes.

@import '~@angular/material/prebuilt-themes/indigo-pink.css';

Step 4: Angular Material Gesture

Some components like Slide Toggle, Slider, and Tooltip rely on a library called HammerJS to capture touch gestures. So, you will need to install HammerJS and import it into our application.

npm install --save hammerjs

Step 5: Angular Material Icons (Optional)

If you want to use the mat-icon component with the official Material Design Icons, load the icon font in your index.html. For more information on using Material Icons, check out the Material icons guide.

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

And yeah, Now you are good to go!

Note:  You can create an app-material module file for importing the angular material components and export them wherever necessary! Let’s write clean code and be a Better programmer!

What Will You Build with Angular Material?

After setting up the project structure and some dependencies, you will be able to start developing apps. You could try out some examples with the built-in components that are provided in Material docs. In this blog, to know about Angular material implementation, we will be implementing it with some small examples that play a major role in any webpage! The idea of this blog is to show how cool and easy it is to use Angular Material.

Example 1: Layout

The most widely used layout is cards. The most basic card needs only an <mat-card> element with some content. However, Angular Material provides a number of preset sections that you can use inside of an <mat-card>. For now, just copy the following code into your HTML file and you could witness a card display!

<mat-card> Simple Card</mat-card>

Example 2: Navigation

Next comes the navigation part of a webpage. <mat-menu> is a floating panel containing the list of options. By itself, the <mat-menu> element does not render anything. The menu is attached to and opened via application of the matMenuTriggerFor directive as follows.

<button mat-button [matMenuTriggerFor]="menu">Menu</button>
 <mat-menu #menu="matMenu">
   <button mat-menu-item>Item 1</button>
   <button mat-menu-item>Item 2</button>
 </mat-menu>

Example 3: Progress Bar

    “Boredom, according to psychologists, is merely lack of stimulation,the unfulfilled desire for satisfying activity. So what if we use the interface to give them that stimulation?”

~ Alice Kotlyarenko

Yeah! The UI progress bar will make you enjoy the wait! Angular Material made it easy to display a progress bar with customizable modes.

<mat-progress-bar mode="indeterminate"></mat-progress-bar>

Conclusion

I hope this blog has helped you understand how to use the power of Material Design in your app for a top-notch UI. For more information about Material Design in Angular 6, check out the official docs which contain ready-to-use templates. It’s a great place to learn about Angular. Thus Angular Material components create a beautiful application without investing too much time thinking about styles. Awesome, right?

Reference:

SwitchMap in rxjs

Let’s dive deep into switchMap with an example, so it helps as to understand what is it and when to use it.

Say we need to implement functionality for traffic signal which consists of 4 roads(A, B, C, D) meeting at a junction. The signals of these roads can be controlled either manually or automatically. The signal change is asynchronous(Observable- data stream).

const roadSignals = Observable.from(['Road SignalA', 'Road SignalB', 'Road SignalC', 'Road SignalD' ]);

roadSignals.subscribe((signal)=>console.log(signal));

Output: 

Road SignalA 

Road SignalB

Road SignalC

Road SignalD

Here comes the next part. We have to allow vehicles to pass through the junction when the signal is ON. Let’s try doing this with the help of the map. (Map -transform the items emitted by an Observable by applying a function to each item. Click here to learn about map )

roadSignals.pipe(

    .map((signal) => changeSignal(signal)),

    .map((allow) => allow.allowVehiclesObservable())

    ).subscribe((vehiclesObservable) => {

        vehiclesObservable.subscribe((vehicle) => console.log(vehicle))

    });

Here the vehicles in roads refer to an observable. So the output will be an Observable inside an Observable. We have to subscribe them in order to get vehicles individually.

In our case, allowVehiclesObservable is the outer Observable and vehiclesObservable is the inner Observable. We need to subscribe the vehiclesObservable(inner Observable) in order to get the vehicles individually. This method is called as FLATTENING.(subscribe inside a subscribe).

Come on let’s do flattening to get vehicles individually.

roadSignals.pipe(

    .map((signal) => changeSignal(signal)),

    .map((allow) => allow.allowVehiclesObservable())

    ).subscribe((vehiclesObservable) => {

        vehiclesObservable.subscribe((vehicle) => console.log(vehicle))

    });

Let a1, a2,.. b1, b2,.. be the vehicles in Road A, B, ..respectively.

Output :

a1

a2

a3

b1

b2

a4

Yes! Now we get vehicles individually. Flattening works:)

Wait a sec. What’s happening. Vehicles from Road A  as well as Road B is also moving. There are chances for accidents. After a few seconds, Signal C and Signal D will go ON. What if the vehicles from all the roads are moving.

 

Oh no. We should stop this. How to do this?

Whenever flattening is used we should use a Flattening Strategy.

  1. We need to store a subscription to the current vehiclesObservable subscription.
let subscription; (declare at top);

subscription = vehiclesObservable.subscribe(vehicle => console.log(vehicle));
  1. If new vehiclesObservable comes in we need to unsubscribe from the previous subscription before we subscribe to the new observable.
if(subscription) subscription.unsubscribe();

subscription = vehiclesObservable.subscribe(vehicle => console.log(vehicle));

Let’s apply the above steps:

let subscription;

roadSignals.pipe(

    map((signal) => changeSignal(signal)),

    map((allow) => allow.allowVehiclesObservable())

).subscribe((vehiclesObservable) => {

    if(subscription){

        subscription.unsubscribe();

    }

    subscription = vehiclesObservable.subscribe((vehicle) => console.log(vehicle))

    });

Output :

a1

a2

b1

b2

b3

c1

c2

SignalA comes first. Initially, the subscription is undefined.  RoadA-vehiclesObservable is stored in the subscription(local variable) and is subscribed. Vehicles from roadA start moving. When SignalB comes in, the subscription is defined (RoadA-vehiclesObservable). The if condition becomes true. Unsubscribe the existing subscription(RoadA-vehiclesObservable) and store the new subscription(RoadB-vehiclesObservable) to get vehicles from road B.No more vehicles from Road A..! When SignalC comes in, the existing subscription (RoadB-vehiclesObservable) is unsubscribed and new RoadC-vehicleObservable is subscribed.

As soon as the outer observable changes we kill the most recent observable and switch to new observable to replace it. Thus unsubscribing from the previous observable before subscribing to the new one is called as SWITCH Strategy.

Yes, we have achieved our desired result. But now,  the problem is the code became complex with observables, two subscribes, subscription, unsubscribe and all of these.

What to do?

Here comes switchMap for our rescue. We can replace the map and inner subscription with switchMap.

roadSignals.pipe(

    map((signal) => changeSignal(signal)),

    switchMap((allow) => allow.allowVehiclesObservable())

).subscribe((vehicle) => {

console.log(vehicle)

    });

Output :

Signal A

   vehicle a1

   vehicle a2

Signal B

   vehicle b1

   vehicle b2

Signal C

   vehicle c1

   vehicle c2

The main difference between switchMap and other flattening operators is the cancellation effect. On each emission, the previous inner observable (the result of the function you supplied) is canceled and the new observable is subscribed. You can remember this by the phrase switch to a new observable.

When to use and avoid switchMap?

switchMap can be used, when a new search is made, pending results are no longer needed; And should be avoided in scenarios where every request needs to complete, think writes to a database. switchMap could cancel a request if the source emits quickly enough.

References: