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.

Export data to excel in Angular.

In this post we will try to learn how to export data (JavaScript array or data) to an excel file using the SheetJS / XLSX library.

Steps:
  • Create the angular app.
  • Add the dependencies, like, xlsx.
  • Create the table in UI.
  • Logic to export data in the table to excel file.
Create the angular app

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

ng new ng-xlsx

Now we have our angular application ready, let’s try to add other dependencies to show table data on the app component and also add the xlsx library.

Add the dependencies
npm i bootstrap lodash xlsx --save

Here we are installing few packages, bootstrap (To display the data in a table), lodash (For performing data manipulation), xlsx (SheetJS library)

We also need @types for lodash, so let’s install that too.

npm i @types/lodash --save-dev
Create the data table

First, we need to import the bootstrap CSS framework into our Angular project so that we can see the styled components / table on the page. Open styles.scss file and add below code.

@import './node_modules/bootstrap/scss/bootstrap';

html,
body {
    font-size: 12px !important;
    margin: 0;
    overflow: hidden;
    width: 100vw !important;
    height: 100vh !important;
}

.page-container {
    padding: 20px;
}

Now open the app component template file (app.component.html) and paste below code, which displays our table.

<div class="page-container">
  <h3>
    {{ title }}
  </h3>
  <div class="row">
    <div class="col-md-12">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">First</th>
                    <th scope="col">Last</th>
                    <th scope="col">Handle</th>
                </tr>
            </thead>
            <tbody>
                <tr *ngFor="let item of users">
                    <th scope="row">{{ item.uid }}</th>
                    <td>{{ item.first }}</td>
                    <td>{{ item.last }}</td>
                    <td>{{ item.handle }}</td>
                </tr>
            </tbody>
        </table>
        <button type="button" class="btn btn-primary" (click)="exportRawDataToExcel(users, title)">Export to Excel</button>
    </div>
  </div>
</div>

And our data in the table is as below, we need to paste it inside the app component script file (app.component.ts).

// Add import statements
import * as XLSX from "xlsx";
import * as _ from "lodash";

// Add below code to the class
title = "ng-xlsx";

users = [
    {
      uid: "1",
      first: "Mark",
      last: "Otto",
      handle: "@mdo",
    },
    {
      uid: "2",
      first: "Jacob",
      last: "Thornton",
      handle: "@fat",
    },
    {
      uid: "3",
      first: "Larry the Bird",
      last: "Thornton",
      handle: "@twitter",
    },
  ];

Run the Angular application.

npm start

Open the app on the browser, http://localhost:4200/ and we should see our table as below.

Table
Export data to excel file

We have our data ready, now let’s write the logic to download this table data to the excel file.

exportRawDataToExcel(tableData: any, fileName: string) {
    if (!tableData || (tableData && tableData.length === 0)) {
      throw new Error("No data to export");
    }
    const wb = XLSX.utils.book_new();
    const data = [];
    const merges = [];
    const headers = [];
    const keys: string[] = _.keys(_.head(tableData));
    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 < tableData.length; j++) {
      const rowData = [];
      for (let k = 0; k < keys.length; k++) {
        rowData.push(tableData[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;
    /**
     * Add worksheet to workbook
     */
    XLSX.utils.book_append_sheet(wb, ws, "Sheet 1");
    XLSX.writeFile(wb, fileName + ".xlsx");
  }

Above code will be overwhelming, so I would suggest to investigate the SheetJS tool and learn few things. But to summarise…

  • The function takes two parameters, first the raw data (JSON / array) and second the file name. The raw data is exported to the excel file and we name the excel file with the given file name in the function parameter.
  • We parse the data to construct into a format that is needed for the xlsx library.
  • Using few functions in the library, like,
    • XLSX.utils.book_new() – Creates a new work book.
    • XLSX.utils.aoa_to_sheet() – Create a new work sheet with the given data (JS array)
    • XLSX.utils.book_append_sheet(wb, ws, “Sheet 1”) – Adds a work sheet to the work book.
    • XLSX.writeFile(wb, fileName + “.xlsx”) – Finally create the excel file.

I guess this is it, when we click the export button below the table we should see a new .xlsx file downloaded with the data as seen in the table!!.

Checkout complete code on Github.

Created my first react application.

I call myself a Web developer but in reality there are many more frameworks and libraries out there that I need to learn so to better myself. One such library is React.

React is very popular, you can tell by looking at the trend below in comparison with Angular.

React vs Angular
So, I started learning react…It’s been few days…and I decided to create my very first react application. It’s that simple.

There are many posts on the web talking about Why react is popular?, two posts I actually like are, this one and this one.

One thing I like about react is its…

Simplicity

Checkout my first react application on Github and let me know what you think!.

I have started another react application called billing to learn more or practise. But I suppose its going to take me some time to finish this application given that I only spend like few hours in a week on side projects on Github.

Export html content to PDF file in Angular using JSPDF.

We already have two posts on using JSPDF in Angular application and also how to export a table to PDF. Check these posts first.

Now to export html content.!

Let’s look at the docs first, and here we have a method called html which takes a HTMLElement as the first arg and few config options as the second arg. So, we can try using this method in our Angular application to export any html content, right?.

Say, for example we have our html content in the template file of our Angular application like below.

<div
    #rentReceiptsDiv
    class="rent-receipts"
    *ngIf="resultsCalculated && !errorModel.errorMsg"
>
    <div class="receipt" *ngFor="let item of receiptDateRanges">
        <div class="row">
            <h3>Rent receipt</h3>
        </div>
        <div class="row pt-2">
            <h6 class="fw-light">
                from {{ item.fromDate | date : 'dd/MM/yyyy' }} to
                {{ item.toDate | date : 'dd/MM/yyyy' }}
            </h6>
        </div>
        <div class="row pt-3">
            <div class="fs-6" [innerHTML]="getDescriptionForPreview(item.fromDate, item.toDate)"></div>
        </div>
        <div class="row pt-5">
            <div class="fs-6">Signature</div>
            <div class="fs-5">{{ _calculatorInputs?.ownerName }}</div>
            <div class="fs-6">{{ _calculatorInputs.ownerPANNumber }}</div>
        </div>
    </div>
</div>

We want to export the above Html content to the PDF file. But the html method in the JSPDF is expecting HTMLElement so to get this object instance of our html content we need to declare the above div element in our component by referencing the id rentReceiptsDiv, so let’s do that.

@ViewChild('rentReceiptsDiv') rentReceiptsDiv: ElementRef;

The ViewChild decorator queries our html template file for the provided id and maintains the reference to it. So, now we have the element reference of our div element that we want to export to PDF. Now, let’s try to export using the html method of the JSPDF library.

downloadReceipts() {
        const fileName = `${this.title}.pdf`;
        const doc = new jsPDF();
        doc.html(this.rentReceiptsDiv.nativeElement as HTMLElement, {
            callback: (d) => {
                d.save(fileName);
            },
            margin: 0,
            autoPaging: true,
            width: 200,
            windowWidth: this.rentReceiptsDiv.nativeElement.clientWidth,
            x: 5,
            y: 0,
        });
    }

As you can see I am making use of the callback function of the html method to export the PDF (save) once it’s ready. I am also passing the div Html element in to the function.

There are also few Html config options you need to be aware of.

Below is the html function definition from the docs.

// jsPDF plugin: html
html(src: string | HTMLElement, options?: HTMLOptions): HTMLWorker;

Also the HTMLOptions definition is as below…We are making use of few of these options, like callback, width, windowWidth. You may have to try few times with these options to get the html rendered correctly.

export interface HTMLOptions {
    callback?: (doc: jsPDF) => void;
    margin?: number | number[];
    autoPaging?: boolean | "slice" | "text";
    filename?: string;
    image?: HTMLOptionImage;
    html2canvas?: Html2CanvasOptions;
    jsPDF?: jsPDF;
    x?: number;
    y?: number;
    width?: number;
    windowWidth?: number;
    fontFaces?: HTMLFontFace[];
}

Checkout complete code base here.