10 tips for improving the performance of Angular applications

1) Use Angular CLI’s production build: When building your Angular application for production, use the Angular CLI’s –prod flag. This enables various optimizations, such as AOT (Ahead-of-Time) compilation (latest angular-cli’s have AOT enabled by default), tree shaking, and minification, which can significantly reduce the bundle size and improve runtime performance. Read more about AOT compiler here.

2) Lazy loading: Implement lazy loading for modules in your application. Lazy loading allows you to load modules on demand, reducing the initial bundle size and improving the application’s startup time. Read below step-by-step guide to create the lazy loading modules.

Step 1: Create a feature module

Create a feature module that you want to lazy load. For this example, let’s assume we have a module called DashboardModule.

// dashboard.module.ts

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

import { DashboardComponent } from './dashboard.component';

const routes: Routes = [
  {
    path: '',
    component: DashboardComponent
  }
];

@NgModule({
  declarations: [DashboardComponent],
  imports: [CommonModule, RouterModule.forChild(routes)]
})
export class DashboardModule {}

Step 2: Configure lazy loading in the main routing module

In the main routing module (usually app-routing.module.ts), configure lazy loading for the DashboardModule using the loadChildren property of the route.

// app-routing.module.ts

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

const routes: Routes = [
  {
    path: 'dashboard',
    loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule)
  },
  // Other routes...
];

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

Step 3: Update the app component template

Update the app component template (usually app.component.html) to include a link to the lazily loaded module.

<!-- app.component.html -->

<h1>Welcome to the App</h1>

<a routerLink="/dashboard">Go to Dashboard</a>

<router-outlet></router-outlet>

In the above example, when the user clicks on the “Go to Dashboard” link, Angular will load the DashboardModule lazily. This means that the module’s code will be loaded only when the user navigates to the /dashboard route, reducing the initial bundle size and improving the application’s startup time.

Lazy loading is a powerful feature of Angular that helps optimize the loading and performance of your application, particularly when dealing with large and complex projects.

Remember to configure the routes and lazy load the modules based on your application’s specific requirements.

3) Change detection strategy: Consider using ChangeDetectionStrategy.OnPush for components where possible. This strategy allows Angular to perform change detection only when input properties change or when triggered explicitly. It reduces the number of change detection cycles and improves performance.

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: `
    <h1>{{ title }}</h1>
    <p>{{ content }}</p>
    <button (click)="updateContent()">Update Content</button>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyComponent implements OnInit {
  title: string;
  content: string;

  ngOnInit() {
    this.title = 'Initial Title';
    this.content = 'Initial Content';
  }

  updateContent() {
    this.content = 'Updated Content';
  }
}

In the above example, the ChangeDetectionStrategy.OnPush is set in the @Component decorator’s changeDetection property. This informs Angular to use the “OnPush” change detection strategy for this component.

With the “OnPush” strategy, change detection will only be triggered when there are changes to the component’s input properties or when explicitly triggered using events like button clicks or HTTP responses. This can help reduce unnecessary change detection cycles for components where the data doesn’t change frequently.

Note: This strategy to work optimally, ensure that the component receives input properties as immutable objects or make use of the Immutable.js library to create immutable objects.

By using the ChangeDetectionStrategy.OnPush strategy, you can optimize the change detection process and improve the performance of your Angular application.

4) TrackBy function: When using Angular’s ngFor directive, provide a trackBy function to optimize rendering. The trackBy function allows Angular to track the identity of items in a list, making updates more efficient and avoiding unnecessary re-rendering of unchanged elements.

import { Component } from '@angular/core';

interface Item {
  id: number;
  name: string;
}

@Component({
  selector: 'app-my-component',
  template: `
    <ul>
      <li *ngFor="let item of items; trackBy: trackByFn">{{ item.name }}</li>
    </ul>
    <button (click)="updateItems()">Update Items</button>
  `
})
export class MyComponent {
  items: Item[];

  constructor() {
    this.items = [
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      { id: 3, name: 'Item 3' }
    ];
  }

  trackByFn(index: number, item: Item): number {
    return item.id;
  }

  updateItems() {
    // Simulating an update to the items array
    this.items = [
      { id: 1, name: 'Updated Item 1' },
      { id: 2, name: 'Item 2' },
      { id: 3, name: 'Updated Item 3' }
    ];
  }
}

In the example above, we have an array of Item objects displayed using ngFor in an unordered list (<ul>). We provide a trackBy function in the *ngFor directive to optimize rendering.

The trackByFn function is defined in the component and takes two arguments: the index of the current item and the item itself. In this case, we use the id property of each Item as the unique identifier for tracking.

By providing the trackBy function, Angular can track the identity of each item based on its unique identifier (id in this case). When the array is updated, Angular can identify which items have changed, allowing it to update only the necessary elements in the DOM, rather than re-rendering the entire list.

This optimization can significantly improve the rendering performance, especially when dealing with large lists or when items in the list have complex structures.

Remember to choose a unique identifier for your items that remains stable across updates, such as an id property.

5) Use Angular’s built-in optimization techniques: Take advantage of Angular’s built-in optimization techniques, such as Angular’s built-in directives (ngIf, ngSwitch, etc.), pipes, and template caching. These features are optimized for performance and can help improve the overall application performance.

6) Avoid unnecessary bindings: Minimize the number of two-way data bindings ([(ngModel)]) and event bindings ((click)) in your templates. Excessive bindings can result in unnecessary change detection cycles and impact performance.

7) Use trackBy with ngFor in large lists: When rendering large lists using ngFor, make sure to use the trackBy function and provide a unique identifier for each item. This helps Angular efficiently update the list when items are added, removed, or reordered.

8) Third party libraries: Minimizing the use of third-party libraries and optimizing their usage is an important aspect of improving the performance of Angular applications. Here are a few things to consider:

  1. Bundle size impact: Third-party libraries can significantly contribute to the size of your application bundle. Each library adds its own set of dependencies and code, which can increase the initial loading time of your application. Choose lightweight libraries whenever possible and avoid using multiple libraries that provide similar functionality.
  2. Optimize imports: Import only the necessary modules, components, or functions from a third-party library instead of importing the entire library. This can help reduce the bundle size and improve loading performance. Many libraries provide modularized exports, allowing you to import only the specific parts you need.
  3. Tree shaking: Take advantage of tree shaking, a process that eliminates unused code during the production build. Ensure that your third-party libraries support tree shaking, as this can significantly reduce the bundle size by removing unused code and dependencies.

9) Optimize heavy computations: Avoid performing heavy computations or complex operations within Angular templates. Move such calculations to component classes or services to offload the rendering thread and improve overall performance.

10) Use Angular Performance Tools: Angular provides various performance tools to help identify and optimize performance bottlenecks in your application. These include the Angular DevTools, which provide insights into change detection, component rendering, and memory usage, and tools like Lighthouse, WebPagetest, or Chrome Performance tab for measuring and analyzing application performance.

By following these tips, you can significantly improve the performance of your Angular applications and provide a better user experience. Remember to profile and measure your application’s performance to identify specific areas for improvement and prioritize optimizations based on your application’s needs.

Building interactive charts with AmCharts in Angular

AmCharts is one of the widely used JavaScript-based interactive charts and maps programming libraries and tools. In this post we will look at how to integrate the AmCharts into Angular project.

Prerequisites

Before getting started, make sure you have the following dependencies installed:

  • Angular CLI: This is used to create and manage Angular projects. If you don’t already have it installed, you can install it by running npm install -g @angular/cli.
Step 1: Create a new Angular project

To create a new Angular project, open a terminal window and run the following command:

ng new ng-amcharts

Replace ng-amcharts with the name of your project. This will create a new Angular project with the specified name and install all the necessary dependencies.

Step 2: Add the dygraphs library to your project

To use AmCharts in your Angular project, you’ll need to first install the dependencies. Navigate to the project’s root directory and install the AmCharts library using npm:

cd ng-amcharts
npm install @amcharts/amcharts4 --save
Step 3: Configure AmCharts in Angular

Open the angular.json file in the project directory and add the AmCharts scripts to the scripts array:

"scripts": [
  "node_modules/@amcharts/amcharts4/core.js",
  "node_modules/@amcharts/amcharts4/charts.js",
  "node_modules/@amcharts/amcharts4/themes/animated.js"
]
Step 4: Create a new component

Generate a new component to display the chart by running the following command:

ng generate component chart
Step 5: Implement the chart component

Open the generated chart.component.ts file and import the necessary AmCharts modules:

import { Component, OnInit, NgZone } from '@angular/core';
import * as am4core from '@amcharts/amcharts4/core';
import * as am4charts from '@amcharts/amcharts4/charts';
import am4themes_animated from '@amcharts/amcharts4/themes/animated';

Next, for the chart component class and implement the chart logic:

@Component({
  selector: 'app-chart',
  templateUrl: './chart.component.html',
  styleUrls: ['./chart.component.scss']
})
export class ChartComponent implements OnInit {
  private chart: am4charts.XYChart | undefined;

  constructor(private zone: NgZone) {}

  ngOnInit() {
    this.zone.runOutsideAngular(() => {
      am4core.useTheme(am4themes_animated);

      // Create chart instance
      let chart = am4core.create('chartdiv', am4charts.XYChart);

      chart.paddingRight = 20;

      let data = [];
      let visits = 10;
      for (let i = 1; i < 366; i++) {
        visits += Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 10);
        data.push({ date: new Date(2018, 0, i), name: "name" + i, value: visits });
      }

      chart.data = data;

      let dateAxis = chart.xAxes.push(new am4charts.DateAxis());
      dateAxis.renderer.grid.template.location = 0;

      let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
      valueAxis.renderer.minWidth = 35;

      let series = chart.series.push(new am4charts.LineSeries());
      series.dataFields.dateX = "date";
      series.dataFields.valueY = "value";

      series.tooltipText = "{valueY.value}";
      chart.cursor = new am4charts.XYCursor();

      let scrollbarX = new am4charts.XYChartScrollbar();
      scrollbarX.series.push(series);
      chart.scrollbarX = scrollbarX;

      this.chart = chart;

    });
  }

  ngOnDestroy() {
    this.zone.runOutsideAngular(() => {
      if (this.chart) {
        this.chart.dispose();
      }
    });
  }
}
Step 6: Create the chart template

Open the generated chart.component.html file and add a element with the id set to “chartdiv“:

<div id="chartdiv" style="width: 100%; height: 500px;"></div>
Step 7: Style the chart component

Open the generated chart.component.css file and add any custom styling you require.

Step 8: Use the chart component

Open the app.component.html file and add the component tag to use the chart component.

<app-chart></app-chart>

And, also don’t forget to declare the chart component in the app.module.ts!!.

That’s it! You have now created an interactive chart using AmCharts in Angular. Go ahead and configure the chart settings, data, series, axes, cursor, and scrollbar based on your specific requirements.

Note: AmCharts is free with one limitation. You can consider buying a license!. PFB screenshot.

Conclusion:
  • We have created a sample angular project using angular-cli.
  • We have integrated AmCharts into Angular project and added a simple line chart component with sample data.

Checkout Github repo for complete code sample!.

Visual Studio Code (vs-code) essentials.

This is how I use the Visual Studio Code (vs-code) as a web developer.

VS Code is a widely used and free IDE that is beloved by the open web community. If you’re a web developer and haven’t heard of or used it before, you may be living under a rock the size of Mount Everest! Just saying… As a web developer myself, I use this IDE frequently and thought I would share how I use it in case it’s useful to others.

Note: There are many articles, posts, and YouTube videos available to help you get started with VS Code and even become a pro. However, I am documenting my own experience with the IDE solely for my personal reference.

Keyboard shortcuts

There is an excellent article about the 20 VS Code shortcuts for faster coding. Any developer loving the VS Code IDE should at-least know few of these shortcuts!!.

Extensions

Below are the list of the extensions I currently use and they are awesome.

Auto Rename Tag
Better Comments
GitLens
JavaScript (ES6) code snippets
Add jsdoc comments
Atom One Dark Theme
Prettier – Code formatter
Github repositories
Angular Language Service
Git Patch
Peacock

Inbuilt features

Below are few of the inbuilt features of the VSCode that you should start using now.

Terminal
Git source control
Command palatte (Cmd + p)

Install nvm and different versions of node.js on Mac.

For developer working with JavaScript and Node.js, you may find it necessary to use different versions of Node.js for different projects. This is where nvm (Node Version Manager) comes in handy. nvm is a command-line tool that allows you to easily install and manage multiple versions of Node.js on your system.

In this tutorial, we’ll see how to install nvm and use it to install different versions of Node.js on a Mac.

Step 1: Install Homebrew

Homebrew is a popular package manager for macOS. It allows you to easily install, update, and manage software packages on your Mac. To install Homebrew, open Terminal and enter the following command:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

**If Homebrew is already installed then you may want to update it:

// First Check the state of the tool first, because if there are any issues its best to fix them
brew doctor

// Now update
brew update
Step 2: Install nvm

With Homebrew installed and updated, you can use it to install nvm. Enter the following command in Terminal:

brew install nvm

This will install nvm on your system.

Step 3: Configure nvm

Once nvm is installed, you’ll need to configure it by adding the following lines to your shell profile (e.g. ~/.bash_profile, ~/.zshrc, or ~/.profile):

export NVM_DIR="$HOME/.nvm"
[ -s "$(brew --prefix)/opt/nvm/nvm.sh" ] && . "$(brew --prefix)/opt/nvm/nvm.sh"

Save the changes to your shell profile and reload it with the following command:

source ~/.bash_profile

Note: If you’re using a different shell, replace ~/.bash_profile with the appropriate file for your shell.

Step 4: Install a version of Node.js

Now that nvm is installed and configured, you can use it to install a specific version of Node.js. To do so, enter the following command in Terminal:

nvm install <version>

Replace with the version of Node.js you want to install (e.g. 14.17.6).

Step 5: Use a version of Node.js

To use a specific version of Node.js, simply enter the following command in Terminal:

nvm use <version>

Replace with the version of Node.js you want to use. See below screenshot.

You can confirm that the correct version of Node.js is being used by entering the following command:

node -v

This will output the version of Node.js that is currently being used. See below screenshot.

Step 6: Install global npm packages

If you need to install global npm packages, you’ll need to do so for each version of Node.js you have installed. To do so, use the following command:

nvm use <version> && npm install -g <package>

Replace with the version of Node.js you want to install the package for, and with the name of the package you want to install.

And that’s it! With nvm installed and configured, you can easily install and manage multiple versions of Node.js on your Mac.

Few tips:

1) How to get the available node versions?.

To List all the available versions of node you can use below command.

nvm ls-remote

Below screenshot shows all the node versions…

2) How to check the installed node versions?.

To check the installed node versions you can use below command.

nvm ls

Below screenshot shows all the installed node version on Mac and also points to the currently selected node, here it’s v14.19.0.

Checkout official website for more info.

Export data to excel sheets using SheetJS in Angular.

In the previous post we have see how to get started with exporting data to excel files using SheetJS / XLSX library.

Now, let’s try create a service class which takes an array for multiple tables data and export the data to sheets in the excel file.

import { Injectable } from "@angular/core";
import * as XLSX from "xlsx";
import * as _ from "lodash";

/**
 * Service class to export data to multiple sheets in an excel file.
 * ! Please check SheetJS docs and research before using this code.
 */
@Injectable({
  providedIn: "root",
})
export class ExcelDataService {

  /**
   * Takes data and file to export data to excel file.
   * @param data Multiple tables data will be accepted.
   * @param fileName Name of the excel file.
   */
  exportRawDataToExcel(data: any[], fileName: string) {
    if (!data || (data && data.length === 0)) {
      throw new Error("No data to export");
    }
    const wb = XLSX.utils.book_new();
    data.forEach((value, index) => {
      /**
       * Add worksheet to workbook
       */
      XLSX.utils.book_append_sheet(
        wb,
        this.getWorkSheet(value),
        `Sheet ${index}`
      );
    });
    XLSX.writeFile(wb, fileName + ".xlsx");
  }

  // Create the worksheet from the data passes.
  private getWorkSheet(sheetData: any[]) {
    const data = [];
    const merges = [];
    const headers = [];
    const keys: string[] = _.keys(_.head(sheetData));
    let mergeAcrossStartC = 0;
    for (let m = 0; m < keys.length; m++) {
      merges.push({
        s: { r: 0, c: mergeAcrossStartC },
        e: {
          r: 0,
          c: mergeAcrossStartC,
        },
      });
      mergeAcrossStartC = mergeAcrossStartC + 1;
      headers.push(keys[m]);
    }
    data.push(headers);
    for (let j = 0; j < sheetData.length; j++) {
      const rowData = [];
      for (let k = 0; k < keys.length; k++) {
        rowData.push(sheetData[j][keys[k]]);
      }
      data.push(rowData);
    }
    const ws = XLSX.utils.aoa_to_sheet(data);

    ws["!cols"] = [];
    _.forEach(headers, (val) => {
      ws["!cols"].push({ wpx: 120 });
    });
    ws["!merges"] = merges;
    return ws;
  }
}

Above code will be overwhelming, so I would suggest to investigate the SheetJS tool.

Most importantly, we are using XLSX.utils.aoa_to_sheet() to create a new sheet with each of the table data.

Checkout complete code on Github.

Installing Java and Maven on Mac.

Java is a popular programming language that is used to build a wide range of applications. Maven is a build automation tool that is often used in Java projects to manage dependencies, compile and test code, and package applications. In this blog post, we will go over the steps to install both Java and Maven on a Mac.

Installing Java on Mac

Download and install the Java Development Kit (JDK):
The Java Development Kit (JDK) is the core component that you need to develop Java applications. You can download the JDK from the Oracle website (https://www.oracle.com/java/technologies/javase-downloads.html). Once you have downloaded the JDK, double-click on the package file and follow the on-screen instructions to install it, or check the link.

Verify the installation:
To verify that Java has been installed successfully, open the terminal and run the following command:

java -version

You should see output that shows the version of Java that is installed on your system, like below.

Installing Maven on Mac

Download Maven:
You can download Maven from the Apache Maven website (https://maven.apache.org/download.cgi). Once you have downloaded Maven, unzip the archive and move the unzipped folder to the location where you want to install Maven (e.g., /usr/local/).

Set the environment variables:
To use Maven from the terminal, you need to set the environment variables that point to the location of the Maven installation. You can set the environment variables by adding the following lines to your .bash_profile file:

export M2_HOME=/usr/local/maven
export PATH=$PATH:$M2_HOME/bin

Verify the installation:
To verify that Maven has been installed successfully, open the terminal and run the following command:

mvn -v

You should see output that shows the version of Maven that is installed on your system, like below.

With these simple steps, you should be able to get both Java and Maven up and running in no time.

Few tips

1) What if you already have Java installed and want to remove / clean previously installed package and start fresh install?.

Check below commands to uninstall Java.

sudo rm -rf /Library/Java/*
sudo rm -rf /Library/PreferencePanes/Java*
sudo rm -rf /Library/Internet\ Plug-Ins/Java*

**You should know what these commands are doing, i.e, removing / uninstalling Java.

You can also check link for uninstall – https://docs.oracle.com/javase/10/install/installation-jdk-and-jre-macos.htm#JSJIG-GUID-577CEA7C-E51C-416D-B9C6-B1469F45AC78

2) What if I want to install legacy version of Java?.

You can download legacy (old / archive) version of Java from different location. Say for example I want to install Java 8, for this I will download JDK from https://www.oracle.com/in/java/technologies/javase/javase8-archive-downloads.html

From here I would download jdk-8u201-macosx-x64.dmg and install Java.

Note: JDK comes bundled with JRE, so no need to download JRE again.

3) How to set JAVA_HOME env variable?

Sometimes env variables don’t work or not set properly, in that case you can do that yourself. Open bash file (vim ~/.zshrc) and add below line.

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home

Test with command – echo $JAVA_HOME on the terminal. You should see the output showing the JAVA_HOME env variable value.

Getting started with Dygraphs in Angular.

Dygraphs is a powerful and flexible open-source charting library that allows you to create interactive and customizable graphs and charts in your Angular applications. In this tutorial, we’ll walk through the steps for integrating dygraphs into an Angular project and creating your first chart.

Prerequisites

Before getting started, make sure you have the following dependencies installed:

  • Angular CLI: This is used to create and manage Angular projects. If you don’t already have it installed, you can install it by running npm install -g @angular/cli.
  • Dygraphs library: To install the Dygraphs library, run npm install dygraphs –save. Also, install the types, npm install @types/dygraphs –save-dev.
Step 1: Create a new Angular project

To create a new Angular project, open a terminal window and run the following command:

ng new ng-dygraphs

Replace ng-dygraphs with the name of your project. This will create a new Angular project with the specified name and install all the necessary dependencies.

Step 2: Add the dygraphs library to your project

To use dygraphs in your Angular project, you’ll need to first install the dependencies.

npm install dygraphs --save

Next, add @types for dygraphs.

npm install @types/dygraphs --save-dev
Step 3: Create a component for your chart

To create a chart with dygraphs, you’ll need to create a component for it. Run the following command to generate a new component:

ng generate component dygraphs-chart

Replace dygraphs-chart with the name of your component. This will create a new component in the src/app/dygraphs-chart directory with the specified name.

Step 4: Add the dygraphs code to your component

Now that you have a component set up, you can add the code to create a chart using dygraphs. Open the src/app/dygraphs-chart/dygraphs-chart.component.ts file and add the following code:

import { Component, ElementRef, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import * as Dygraph from 'dygraphs';

@Component({
  selector: 'app-dygraphs-chart',
  templateUrl: './dygraphs-chart.component.html',
  styleUrls: ['./dygraphs-chart.component.scss'],
})
export class DygraphsChartComponent implements OnInit, AfterViewInit {

  @ViewChild('dygraphsChart') dygraphsChart!: ElementRef;
  data = [
    [1, 10, 100],
    [2, 20, 80],
    [3, 50, 60],
    [4, 70, 80],
  ];
  options = {
    width: 500,
    height: 300,
    labels: ['X', 'Y1', 'Y2'],
  };

  constructor() {}

  ngOnInit(): void {}

  ngAfterViewInit() {
    new Dygraph.default(
      this.dygraphsChart.nativeElement,
      this.data,
      this.options
    );
  }
}

Lets also add code to our template file, Open the src/app/dygraphs-chart/dygraphs-chart.component.html file and add the following code:

<div class="dygraphs-chart" #dygraphsChart></div>

Run the application ng serve or npm start, you should see a line chart!!.

I hope this helps somebody!, drop a comment if any questions.

Conclusion:
  • We have created a sample angular project using dygraphs.
  • We have added a simple line chart with sample data to the component.

Checkout Github repo for complete code sample!.

Creating a structural directive in Angular.

Custom structural directives in Angular allow you to define your own HTML syntax and behavior for creating dynamic templates. They are used to manipulate the DOM in a declarative manner, making it easier to read and understand the intended structure and behavior of a template.

Structural directives are recognizable by the * symbol that precedes the directive name. For example, the built-in *ngFor directive is used to loop over a list of items and render them in the template.

To create a custom structural directive, you first need to import the Directive decorator from the @angular/core module and use it to define a class for your directive. The class should implement the OnChanges lifecycle hook, which is called whenever the input bindings of the directive are updated.

import { Directive, OnChanges } from '@angular/core';

@Directive({
  selector: '[appMyDirective]'
})
export class MyDirective implements OnChanges {
  ngOnChanges() {
    // code to handle changes to input bindings
  }
}

In the ngOnChanges method, you can access the updated input bindings through the SimpleChanges object that is passed to the method. You can then use this information to manipulate the DOM as needed.

To use your custom structural directive in a template, you simply add the * symbol before the directive name in the element where you want it to be applied. For example:

<div *appMyDirective>
  ...
</div>

You can also pass input bindings to your directive, just like with any other Angular directive. For example:

<div *appMyDirective="someInputValue">
  ...
</div>

Custom structural directives are a powerful way to extend the capabilities of Angular templates and provide a clean and declarative syntax for complex DOM manipulation. They can help you make your templates more readable and maintainable, and enable you to write reusable and modular code for your Angular applications.

Getting started with date-fns in Angular.

In this post we will learn how to use date-fns in Angular application. But first let’s understand date-fns.

date-fns is a date utility library which provides simple and extensive set of functions to manipulate JavaScript dates.

For example, say we want to present to user a particular date-time based on a time-zone instead of a date based on the system / browser time-zone (typically working with UTC is easy), this is actually difficult to do until unless you are using some library which parses dates into time-zones. date-fns provides nice set of functions to achieve this.

utcToZonedTime(new Date('2018-09-01T16:01:36.386Z'), 'America/Chicago')

Above function parses the UTC date into a date with the specified time-zone, i.e representing a local time in that time-zone.

Now, let’s get stated with the Angular project.

Steps:
  • Create the angular app.
  • Add the project dependencies, like, date-fns.
  • Use the library functions from date-fns.
  • Create a simple pipe service for date-fns to format dates in the template.
Create the angular app

We are going to use the angular guide to create a new angular project.

ng new ng-date-fns

Now we have our angular application ready, let’s try to add the dependencies.

Add the dependencies
npm i bootstrap date-fns --save

Here we are installing few packages, bootstrap (To display the data in a table) and date-fns (JavaScript date utility library).

Using the library
// Library is tree-shakable, import only what is needed.
import format from 'date-fns/format';

format(new Date(), 'MM/dd/yyyy');

Here, one advantage of using date-fns is its tree-shakable, we can just import only what is needed, which compiles to less bundle size!.

Pipe service
import { Pipe, PipeTransform } from '@angular/core';
import format from 'date-fns-tz/format';
import utcToZonedTime from 'date-fns-tz/utcToZonedTime';

@Pipe({
    name: 'datefns'
})
export class DateFnsPipe implements PipeTransform {
    transform(value: any, timeZone: string, pattern: string, defaultText: string = "Invalid date!") {
        if (!value) {
            return defaultText;
        }
        if (timeZone) {
            const zonedDate = utcToZonedTime(value, timeZone);
            return format(zonedDate, pattern, { timeZone });
        }
        return format(value, pattern);
    }
}
// Use the pipe in the template
<td>{{ utcDate | datefns:'Europe/Berlin':'MMM dd yyyy, hh:mm aa' }}</td>

**You would also need to declare the pipe in the module.

I guess thats it…we have started to use the date-fns in Angular project.

Checkout complete code at Github. And don’t forget to like or share, you can also leave a comment!!, thanks.