How to read the excel file in angular with XSLX package

Here we add example code for fetching data from excel.

Add XLSX package to the angular project

npm install xlsx –save

read excel data in angular

Download demo Excel

app.component.ts

uploadExcel(e) {
  
  try{
  
  const fileName = e.target.files[0].name;
  
  import('xlsx').then(xlsx => {
    let workBook = null;
    let jsonData = null;
    const reader = new FileReader();
    // const file = ev.target.files[0];
    reader.onload = (event) => {
      const data = reader.result;
      workBook = xlsx.read(data, { type: 'binary' });
      jsonData = workBook.SheetNames.reduce((initial, name) => {
        const sheet = workBook.Sheets[name];
        initial[name] = xlsx.utils.sheet_to_json(sheet);
        return initial;
      }, {});
      this.products = jsonData[Object.keys(jsonData)[0]];
      console.log(this.products);

    };
    reader.readAsBinaryString(e.target.files[0]);
  });

}catch(e){
   console.log('error', e);
}

}

app.component.html

 <input type="file" (change)="uploadExcel($event)">

  <table >
    <thead>
      <tr>
        <th>#</th>
        <th>Product Identity</th>
        <th>Product Name</th>
        <th>Product Price</th>
        <th>Seller Name</th>
        <th>Total Count</th>
        <th>Status</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let product of products; let i = index">
      <td>{{i+1}}</td>
        <td>{{product.identity}}</td>
        <td>{{product.name}}</td>
        <td>{{product.price}}</td>
        <td>{{product.sellerName}}</td>
        <td>{{product.count}}</td>
        <td>{{product.status}}</td>
      </tr>
    </tbody>
  </table> 

app.component.css

table{
  width:75%;
  margin:20px auto;
}
table tr td, table tr{
  border-collapse: collapse;
  border:1px solid #ccc;
  font-size:14px;
}

I hope this will help. If any queries feel free to comment below.

Top ten Javascript tricks – part 1

Convert a string to an array of Characters using spread Syntax – ES6

// Split string uisng ES6 Spread
const angular  = 'angular';

//  old ways
const splicedAngualr = angular.split('');
// [ 'a', 'n', 'g', 'u' , 'l' , 'a' ,'r']

// new ES6 way
const splicedAngular = [...angular]
// [ 'a', 'n', 'g', 'u' , 'l' , 'a' ,'r']

Addition string (’10’) and number (5)

const str = '10';
const num = 5;

// This doesn't returnt the sum, its concatenated
str + num
// 105 (not correct)

//prepend string with "+" to calculate the sum
+str + num
// 15 (correct)

How to remove an Array Duplicates

const duplicates = [1, 2, 2, 4 , 5, 5, 6, 6];

const uniques = Array.from(new Set(duplicates));

// uniques [1, 2, 4, 5, 6]

3 ways to convert string to boolean

const isBool = 'Helperscript';

new Boolean(isBool) // true

Boolean(isBool) // true

!!isBool // true

How to check if NaN equals to NaN?

const item = NaN;

// this doesn't work
item === NaN; // false

//This works!
Object.is(item, NaN); // true

Two ways to repeat the strings

const str = 'J';

// 1. Repeat
str.repeat(3);

// 2. Fill
Array(3).fill(str).join('');

// result 'JJJJ'

Refactoring the ‘if’ condition

const isPerson = false;

//not correct
if(isPerson === false)

// correct
if(!isPerson)

Check if a string contains Substring

const word ='summer';

// old way
word.indexOf('sum') !=== -1 // true

// ES6 way
word.includes('sum');

Check the number is Negative or Positive

const num = -2;

// old ways
num === 0 ? num : (num > 0 ? 1 : -1) // -1

// ES6
Math.sign(num); // -1 if positive return 1 

The standard naming pattern for boolean variable

// Non standard
const person =  false;
const age = false;
cosnt dance = false

// Good standard
const isPerson =  true;
const hasAge = true;
cosnt canDance = true

I hope this will helpful for most beginners as well as to everyone. Thanks for reading. If you know any tricks comment below.

Javascript tricks part2 >

create angular CDK multi drag, drop and multi sorting

Why this post?

Angular CDK has beautiful drag, drop, and sort facilities, but we only able to move only one at a time. So, I give a solution to move with multiple selections of lists.

Angular CDK multi drag and drop with sorting video

Let see step by step from the package installation requirement.

npm i @angular/cdk

Step 1 – Next to import the needed module

import {DragDropModule} from ‘@angular/cdk/drag-drop’;

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import {DragDropModule} from '@angular/cdk/drag-drop';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,FormsModule,CommonModule, DragDropModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

I am using bootstrap jquery for Front End. If you don’t know how to import in angular. See this link.

Step 2 – Import some services like moveItemInArray, transferArrayItem form CDK drag-drop module.

import { CdkDragDrop, moveItemInArray, transferArrayItem } from ‘@angular/cdk/drag-drop’;

app.component.ts

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

import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';

declare var $: any;
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  public tasks = [{
    title: 'All Tasks',
    taskList: [{
      id: 1,
      selected: false,
      name: 'Task 1'
    }, {
      id: 2,
      selected: false,
      name: 'Task 2'
    }, {
      id: 3,
      selected: false,
      name: 'Task 3'
    }, {
      id: 4,
      selected: false,
      name: 'Task 4'
    }, {
      id: 5,
      selected: false,
      name: 'Task 5'
    }, {
      id: 6,
      selected: false,
      name: 'Task 6'
    }, {
      id: 7,
      selected: false,
      name: 'Task 7'
    }, {
      id: 8,
      selected: false,
      name: 'Task 8'
    },
    {
      id: 9,
      selected: false,
      name: 'Task 9'
    }, {
      id: 10,
      selected: false,
      name: 'Task 10'
    },
    ]
  }, {
    title: 'Monday',
    taskList: []
  }, {
    title: 'Tuesday',
    taskList: []
  }, {
    title: 'Wednesday',
    taskList: []
  }, {
    title: 'Thursday',
    taskList: []
  }, {
    title: 'Friday',
    taskList: []
  }
  ];
  public ctrlPress = false;
  public dragData = [];
  public stored = [];
  public sortIndex = [];

  ondragging(event, item, data) {
    this.dragData = data;
    const a = this.stored.findIndex(x => x.id === item.id);

    if (a === -1) {
      item.selected = true;
      let idx = data.indexOf(item);
      this.sortIndex.push(idx);
      this.sortIndex.sort();
      this.stored = [];
      this.sortIndex.forEach(i => {
        data[i].selected = true;
        this.stored.push(data[i]);
      });

    } else {

    }



    $('.selected').addClass('dragging');

    $('.cdk-drag-placeholder').css({ 'opacity': '0 !important' });


  }


  drop(event: CdkDragDrop<any[]>, dropdata) {
    $('.selected').removeClass('dragging');
    $('.selected').css({ 'opacity': 1 });
    $('.cdk-drag-placeholder').css({ 'opacity': 1 });
    if (this.stored.length === 1) {
      if (event.previousContainer === event.container) {
        moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
      } else {
        transferArrayItem(event.previousContainer.data,
          event.container.data,
          event.previousIndex,
          event.currentIndex);
      }
      this.stored = [];
      event.container.data.forEach((d) => {
        d.isMultidragging = false;
        d.selected = false;
      });
    } else {
      const storedCloner = JSON.parse(JSON.stringify(this.stored));
      if (event.previousContainer === event.container) {
        let b = event.currentIndex;
        const clonerdata = Object.assign([], event.previousContainer.data);

        const extra = Math.max.apply(Math, this.sortIndex.map((o) => { return o; }));
        if (extra < b) {
          b = b + 1;
        }
        clonerdata.forEach((elem, i) => {
          if (elem.selected) {
            const b = dropdata.findIndex(x => x.id === elem.id);
            dropdata[b].id = 0;

          }
          if (clonerdata.length === (i + 1)) {
            storedCloner.slice(0).reverse().forEach((item, idx) => {
              dropdata.splice(b, 0, item);
              if (storedCloner.length === (idx + 1)) {
                setTimeout(() => {
                  dropdata.forEach((el, index) => {
                    if (el.id === 0) {
                      dropdata.splice(index, 1);
                    }
                  }, 1000);
                });

              }
            });
          }
        });


        this.stored = [];
        event.container.data.forEach((d, id) => {
          if (d.id === 0) {
            event.container.data.splice(id, 1);
          }

          d.isMultidragging = false;
          d.selected = false;
        });


      } else {
        if (this.stored.length > 0) {
          event.previousContainer.data.slice(0).reverse().forEach((item, idx) => {
            if (item.selected) {
              event.previousContainer.data.splice(event.previousContainer.data.indexOf(item), 1);

              event.container.data.splice(event.currentIndex, 0, item)
              event.container.data.forEach((d) => {
                // d.isMultidragging=false;
                d.selected = false;
              })

            }
          });
          this.stored = [];

        } else {

          transferArrayItem(event.previousContainer.data,
            event.container.data,
            event.previousIndex,
            event.currentIndex);
          event.container.data.forEach((d) => {
            d.isMultidragging = false;
            d.selected = false;
          });
          this.stored = [];

        }
      }

    }

    this.sortIndex = [];


  }

  onKeyDown(e, item, data) {
    this.ctrlPress = e.ctrlKey;
    if (e.ctrlKey) {
      const idx = data.indexOf(item);
      this.sortIndex.push(idx);

      this.stored = [];
      const result = [];
      const map = new Map();
      for (const item of this.sortIndex) {
        if (!map.has(item)) {
          map.set(item, true);    // set any value to Map
          result.push(item);
        }
      }
      this.sortIndex = result;
      this.sortIndex.forEach(i => {

        data[i].selected = true;
        this.stored.push(data[i]);

      });
    }

  }

}

The above code has all functions like
1. ondragging() // drag started
2. drop() // on drop the dragged data
3. onKeyDown() // selection of list

We have a task list in the above example for Monday to Friday to assign the task.

ondragging() function doing when dragging the unselected element its check and added to the already item selected to drag. So when dropped if any selected item there will also be dropped into the container.

drop() function – It helps to drop the task in one container and remove the task from the previous container.

onKeyDown() function – It helps to select an item or deselect an item from the task list.

Step 3 – Add HTML for the front end view

app.component.html

<div class="container-fluid mt-2">
  <div class="container" cdkDropListGroup>
    <div class="row d-flex justify-content-start">

      <div class="col-md-4 mb-3" *ngFor="let task of tasks; let i = index">
        <div class="card">
          <div class="header">
            <h6 class="p-2 bg-secondary text-white text-uppercase">{{task.title}}</h6>

          </div>
          <div class="card-body p-0" style="height:300px;overflow:auto" cdkDropList [cdkDropListData]="task.taskList"
            (cdkDropListDropped)="drop($event, task.taskList)">
            <ul class="list-group">

              <li class="list-group-item border" *ngFor="let t of task.taskList" cdkDrag
                (cdkDragStarted)="ondragging($event, t, task.taskList)" (click)="onKeyDown($event, t, task.taskList)"
                [ngClass]="{'border-primary':t.selected,'selected':t.selected}">{{t.name}}
                <div *cdkDragPreview>
                  <ul class="list-group">
                    <li class="list-group-item border" *ngFor="let s of stored" style="min-width:200px;">{{s.name}}</li>
                  </ul>
                </div>
              </li>
            </ul>
          </div>

        </div>

      </div>

    </div>

  </div>
</div>

Important to know the details of
1. cdkDropListGroup
2. cdkDropList
3. [cdkDropListData]
4. (cdkDropListDropped)
5. cdkDrag
6. (cdkDragStarted)

cdkDropListGroup => If you add to the top of the drag-drop containers. It says any drop list can able to accept the dragging data. If you want to some container will accept only form particular then you can use [cdkDropListConnectedTo] . Its an array you can push the reference in to drop list connected.

cdkDropList => It says that the container will accept the dragging data.

[cdkDropListData] => You will add task list data into this.

(cdkDropListDropped) => It is an event triggering when dropping initiated.

cdkDrag => Which says that the elements are draggable.

(cdkDragStarted) => It is an event triggering when drag started.

Step 4 – Add some CSS for better visibility.

app.component.css

.card-body::-webkit-scrollbar {
  width: 7px;
}
 
.card-body::-webkit-scrollbar-track {
  box-shadow: inset 0 0 10px transparent;
}
 
.card-body::-webkit-scrollbar-thumb {
  background-color: #c1c1c1;;
 border-radius:3.5px;
}
.selected.dragging{
  opacity:0.2;
}
.selected.dragging.cdk-drag-placeholder{
  opacity:0 !important;
}

That’s all. I hope this code will help you with something. Thanks for reading.

NOTE: If any queries feel free to ask in comment.

angular ng-filter-search to any component like table, list, div and etc

ng-filter-search

npm install ng-filter-search –save

Step1: Import FilterSearchModule to module.ts

https://www.npmjs.com/package/ng-filter-search

import {FilterSearchModule} from 'ng-filter-search';
@NgModule({
imports: [
    
    FilterSearchModule
  ]
})

step2: Import FilterSearchService to component.ts

import { Component } from '@angular/core';
import {FilterSearchService} from 'ng-filter-search';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public productList: any;
  // productList must be a type any.
  public cloner = [];
  // searchMap is defined to which key to filter
  public searchMap = ['name', 'price', 'sellerName', 'status'];
 
  constructor(private fs: FilterSearchService){
// dummy productList you can load from your api
    this.productList = [{
      id: 1,
      identity: 11012,
      name: 'Blue Headset',
      price: '$123',
      sellerName: 'Alibaba',
      count: 12,
      status: 'Sold Out'
    },
    {
      id: 2,
      identity: 31012,
      name: 'Red Shoe',
      price: '$143',
      sellerName: 'Amazon',
      count: 2,
      status: 'Available'
    },
    {
      id: 3,
      identity: 6423,
      name: 'Red Shoe',
      price: '$123',
      sellerName: 'FlipKart',
      count: 5,
      status: 'Available'
    },
    {
      id: 4,
      identity: 64123,
      name: 'Mi Phone',
      price: '$1123',
      sellerName: 'FlipKart',
      count: 11,
      status: 'Sold out'
    },
    {
      id: 5,
      identity: 86423,
      name: 'Redmi pro',
      price: '$223',
      sellerName: 'Alibaba',
      count: 9,
      status: 'Available'
    }];
    // this.cloner is important to copy your productList
    this.cloner = [...this.productList];
  }
 
  onSearchChange(sval: string): void {
    // Use filterSearch() function to filter the data
    this.productList =  this.fs.filterSearch(sval, this.cloner, this.searchMap);
}
}

HTML

Table Filter search

<input placeholder="SEARCH FILTER" (input)="onSearchChange($event.target.value)" />
 
<table>
    <thead>
      <tr>
        <th>#</th>
        <th>Product Identity</th>
        <th>Product Name</th>
        <th>Product Price</th>
        <th>Seller Name</th>
        <th>Total Count</th>
        <th>Status</th>
      </tr>
    </thead>
    <tbody>
    // productList is an array of an object from which we need to filter
      <tr *ngFor="let product of productList; let i = index">
      <td>{{i+1}}</td>
        <td>{{product.identity}}</td>
        <td>{{product.name}}</td>
        <td>{{product.price}}</td>
        <td>{{product.sellerName}}</td>
        <td>{{product.count}}</td>
        <td>{{product.status}}</td>
      </tr>
    </tbody>
  </table>

For list

<input placeholder="SEARCH FILTER" style="float:left" (input)="onSearchChange($event.target.value)" />
 
  <ul>
    <li *ngFor="let product of productList">{{product.name}}</li>
  </ul>

You can apply this filter for any search filter.

angular2 multi-select update data not working in an array

Hi! In this article, we learn something trick in angular. Sometimes angular 2 multi-select does not update after pushing the new data into the array.

Let’s have an example :
I had a dropdown list of country, I need to add a new country to the dropdown list.

this.dropdownList = [ { “id”: 1, “itemName”: “India” }, { “id”: 2, “itemName”: “Singapore” }, { “id”: 3, “itemName”: “Australia” }, ]

I need to add Canada to this list. So EveryOne did the same logic was to push data into an array using push() method in javascript. Like

this.dropdownList.push({id:4, itemName: ‘Canada’})

That’s fine. But sometimes this push method not update in your dropdown list. It’s not shown to your front end.

Let see a solution to such a situation. What I suggest just clone the old data and empty the current and reassign it to the list.

let cloner = […this.dropdownList]; this.dropdownList = []; // It may need or not need. this.dropdownList = cloner;

Example:
angular 2 multi-select: HTML5

angular 3 multi-select: .ts file

export class AppComponent { dropdownList = []; selectedItems = []; dropdownSettings = {}; ngOnInit() { this.dropdownList = [ { “id”: 1, “itemName”: “India” }, { “id”: 2, “itemName”: “Singapore” }, { “id”: 3, “itemName”: “Australia” }, ] this.dropdownSettings = { singleSelection: false, text: “Select Countries”, selectAllText: ‘Select All’, unSelectAllText: ‘UnSelect All’, enableSearchFilter: true, classes: “myclass custom-class” }; } onItemSelect(item: any) { console.log(item); console.log(this.selectedItems); } OnItemDeSelect(item: any) { console.log(item); console.log(this.selectedItems); } onSelectAll(items: any) { console.log(items); } onDeSelectAll(items: any) { console.log(items); } addCountry(){ this.dropdownList.push({id: 4, itemName: ‘Canada’}) } }

I hope this will helpful to you. Thank you for reading. If you like this please comment below. It will encourage me.

primeNg picklist alternative with listbox in angular

Pick-list angular PrimeNg alternative using ListboxModule

View demo Video

Hi! we had solution for how to remove buttons from picklist in PrimeNg. Unfortunately PrimeNg picklist not having options to remove left and right side of buttons. So, here the solutions we provide.

Let’s see step by step from installation

npm install primeng primeicons –save

After install the packages of primeng, add styles to angular.json file.

"styles": [
              "node_modules/primeicons/primeicons.css",
              "node_modules/primeng/resources/themes/nova-light/theme.css",
              "node_modules/primeng/resources/primeng.min.css",
              "src/styles.css"
            ],

After adding the style. Import the component we using. Here we use ListboxModule from Primeng/listbox.

import {ListboxModule} from 'primeng/listbox';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
...
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    ListboxModule
    ...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now lets jump into integration of custom picklist via listbox in PrimeNg

app.component.html

<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            <p-listbox [options]="users" filter="filter" multiple="true" checkbox="true"
            [style]="{'width':'100%'}" [listStyle]="{'max-height': '200px'}" [metaKeySelection]="false"
            [(ngModel)]="selectedUserList"></p-listbox>
        </div>
        <div class="col-md-2">
            <div class="my-2 ml-3"><i class="pi pi-angle-double-right clickable"
                (click)="moveUserToGroupMember()"></i></div>
            <div class="my-2 ml-3"><i class="pi pi-angle-double-left clickable" 
                (click)="moveGroupToUser()"></i></div>
        </div>
        <div class="col-md-3">
            <p-listbox [options]="groupUserList" filter="filter" multiple="true" checkbox="true"
            [style]="{'width':'100%'}" [listStyle]="{'max-height': '200px'}" [metaKeySelection]="false"
            [(ngModel)]="selectedGroupUsersList"></p-listbox>
        </div>
    </div>
</div>

I am using bootstrap for styling. If you don’t know how to import bootstrap to your app. See this link.

Now very interesting part. our custom picklist operations and functions.

app.component.ts


export class AppComponent {
public users = [];
public groupUserList = [];
public selectedUserList:any;
public selectedGroupUsersList:any;
constructor AppComponent(){
this.users = [
    { label: 'Ganesh', value: '3' },
    { label: 'John', value: '1' },
    { label: 'Joshua', value: '2' },


  ];
  this.groupUserList = [
    { label: 'Vetri', value: '5' },
    { label: 'shiva', value: '6' },
  ];
};


  moveUserToGroupMember() {
    this.users.forEach((elem, index) => {
      this.selectedUserList.forEach((selUser, indexes) => {
        if (selUser === elem.value) {
          this.groupUserList.push(elem);
          setTimeout(() => {
            this.removeByAttr(this.users, 'value', selUser);
          }, 500);
        }
      });
    });
  }
  moveGroupToUser() {
    this.groupUserList.forEach((elem, index) => {
      this.selectedGroupUsersList.forEach((selUser, indexes) => {
        if (selUser === elem.value) {
          this.users.unshift(elem);
          setTimeout(() => {
            this.removeByAttr(this.groupUserList, 'value', selUser);
          }, 500);
        }
      });
    });
  }

  removeByAttr = (arr, attr, value) => {
    let i = arr.length;
    while (i--) {
      if (arr[i]
        && arr[i].hasOwnProperty(attr)
        && (this.users.length > 0 && arr[i][attr] === value)) {

        arr.splice(i, 1);

      }
    }
    return arr;
  }

}

You can get selected Users from selectedUserList:any and selectedGroupUserList:any. That’s it now you can able to move users from one list to another list. Hope it will help to you. Further queries below in comment section. Have a great day!.

How to generate pdf in angular with the table and image from Client-side | Server-side

Pdf generate from angular with table images

To generate pdf from the client side with images. We need to convert the image to base 64. Let’s see how to convert images to base64 from our table data.

Example – My case table data look like:

tabledata = [{
    img: 'https://i.picsum.photos/id/258/536/354.jpg',
    name: 'Joseph',
    domain: 'Angular 9'
  },
  {
    img: 'https://i.picsum.photos/id/258/536/354.jpg',
    name: 'Vani',
    domain: 'Angular 8'
  }, {
    img: 'https://i.picsum.photos/id/258/536/354.jpg',
    name: 'Raj',
    domain: 'React.js'
  },
  ];

We need to convert the image  from Image URL to base64

Base64 conversion function code:

convertImagetoBase64(url, callback) {
    const xhr = new XMLHttpRequest();
    xhr.onload = () => {
      const reader = new FileReader();
      reader.onloadend = () => {
        callback(reader.result);
      };
      reader.readAsDataURL(xhr.response);
    };
    xhr.open('GET', url);
    xhr.responseType = 'blob';
    xhr.send();
  }

Let convert the image URL to base64 before we bind to the table in HTML.

  this.tabledata.forEach(elem => {
      this.convertImagetoBase64(elem.img, (b64Img) => {
        elem.img = b64Img;
      });

After that we applying to HTML. If you don’t want to show in HTML of pdf generation you can simply apply style display: none to the table but your table will generate in pdf.

I have a different table in HTML.

<style>
    td, th{
        border:1px solid #ccc;
        padding:10px 15px;
    }
</style>
 
<table id="pdfConvert">
    <thead>
        <tr><th>Head 1</th>
        <th>Head 2</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>value 00</td>
            <td>value 01</td>
        </tr>
        <tr>
            <td>value 10</td>
            <td>value 11</td>
        </tr>
    </tbody>
</table>
 
 
<table id="imgTable" style=”display:none”>
    <thead>
        <tr><th>Name</th>
        <th>Domain</th>
        <th>Image</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let data of tabledata">
            <td>{{data.name}}</td>
            <td>{{data.domain}}</td>
            <td><img src="{{data.img}}" width="100" height="100" /></td>
        </tr>
       
    </tbody>
</table>
 
<button (click)="generatePdf()">Generate Pdf</button>

Each table has a id. This id attribute is the reference for generating pdf.

Before Generation, we need to install 

npm install jspdf jspdf-autotable

For more reference: https://github.com/simonbengtsson/jsPDF-AutoTable

Let import the jspdf and jspdf-autoble to your .ts file

component.ts file:

import jsPDF from 'jspdf';
import 'jspdf-autotable';

Then generate pdf function look like:

generatePdf() {
    const doc = new jsPDF('l');
    // Heading
    doc.autoTable({
      columnStyles: {
        0: { cellWidth: 40, fillColor: '#fff', fontStyle: 'bold', fontSize: '11', textColor: '#000' },
        1: { cellWidth: 20, fillColor: '#fff', fontStyle: 'normal', fontSize: '11', textColor: '#fc0' },
        2: { fillColor: '#fff', fontStyle: 'normal', fontSize: '11', textColor: '#000' },
 
      }, // Cells in first column centered and green
      body: [
        ['Main Heading', 'Date', new Date()]
      ],
    });
    // Table 1
    doc.autoTable({
      html: '#pdfConvert'
    });
 
    // Table 2
    doc.autoTable({
      html: '#imgTable',
      bodyStyles: { minCellHeight: 20 },
      theme: 'grid',
      styles: { valign: 'middle', overflow: 'linebreak', halign: 'center', minCellHeight: 21 },
      pageBreak: 'avoid',
      columnStyles: {
        2: { cellWidth: 22, minCellHeight: 22 },
      },
      headStyles: { fillColor: '#f2f2f2', textColor: '#000', fontStyle: 'bold', lineWidth: 0.5, lineColor: '#ccc' },
      didDrawCell: (data) => {
        if (data.column.index === 2 && data.cell.section === 'body') {
          const td = data.cell.raw;
          const img = td.getElementsByTagName('img')[0];
          // let dim = data.cell.height - data.cell.padding('vertical');
          // let textPos = data.cell.textPos;
          doc.addImage(img.src, data.cell.x + 1, data.cell.y + 1, 19, 19);
 
        }
      }
    });
    // Table 3
    doc.autoTable({
      styles: { lineColor: 'red' },
      theme: 'grid',
      html: '#pdfConvert'
    });
 
    doc.save('yourpdfname.pdf');
 
  }

Then try to generate the pdf. 

Issue from cors policy.

Note: If you face any issue like the above image. This is just a CORS policy issue. This is about the image URL is not belongs to you. You don’t use the copyrighted image. Use your own image URL or some free lorem ipsum image URL.

Thanks for reading. I hope this will helpful to you. Have a nice day. If you have any queries your inputs are welcome in comment sections.

Create a module with routing in angular and make it as the main module

When we create an angular app from angular CLI, the main module as app.module.ts. But how to change that and learn about the flow of the angular application. In this article, we learn some basic errors too.

Errors we going to see here:

  • Error: No ErrorHandler is platform module browser module included
  • Error: The selector app-main did not match any element
  • Error: The module EcommerceModule was bootstrapped, but it does not declare “@NgModule.bootstrap” components nor a “ngDoBootstrap” method

Let’s start to create a new module.
To create the main module manually. Go to Terminal type command to create a module with routing.

ng g m ecommerce –routing

  • ng – define angular
  • g – Generate
  • m – module
  • ecommerce – name of the module
  • –routing –  define routing add to this module
ng generate module ecommerce –routing

Go to main.ts file and remove AppModule and add your newly created module. In my case, the module name is EcommerceModule.

Import <newModule> from ‘<path>‘;

import { EcommerceModule } from ‘./app/ecommerce/ecommerce.module’;

Then add your Imported Module to 

PlatformBrowserDynamic().bootstrapModule(EcommerceModule).catch(err => console.error(err));

Code: main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 
// import { AppModule } from './app/app.module';
import { EcommerceModule } from './app/ecommerce/ecommerce.module';
import { environment } from './environments/environment';
 
if (environment.production) {
  enableProdMode();
}
 
// platformBrowserDynamic().bootstrapModule(AppModule)
// change this AppModule to newly created module
 
platformBrowserDynamic().bootstrapModule(EcommerceModule)
  .catch(err => console.error(err));

Then create a component for main module. Go to path of EcommerceModule and Type in terminal.

ng g c main

Add your component in ecommerce-routing.module.ts

Code: ecommerce-routing.module.ts

import { MainComponent } from './main/main.component';
 
 const routes: Routes = [
  { path: '', component: MainComponent }, 
 // add this newly created component.
];
 
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class EcommerceRoutingModule { }

Now, Try to run with command “ng serve”. Go to browser type http://localhost:4200. Inspect and Let see our error cases.

Error: The module EcommerceModule was bootstrapped, but it does not declare “@NgModule.bootstrap” components nor a “ngDoBootstrap” method

Error: The module EcommerceModule was bootstrapped, but it does not declare “@NgModule.bootstrap” components nor a “ngDoBootstrap” method

Solution: add bootstrap: [MainComponent] to your module.ts

Code: ecommerce.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { EcommerceRoutingModule } from './ecommerce-routing.module';
import { MainComponent } from './main/main.component';


@NgModule({
  declarations: [MainComponent],
  imports: [
    CommonModule,
    EcommerceRoutingModule
  ],
  bootstrap: [MainComponent],
})
export class EcommerceModule { }

Error: No ErrorHandler is platform module browser module included

Error: No ErrorHandler is platform module browser module included

Solution: add “BrowserModule” to your module file.

Code: ecommerce.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { EcommerceRoutingModule } from './ecommerce-routing.module';
import { MainComponent } from './main/main.component';


@NgModule({
  declarations: [MainComponent],
  imports: [
    CommonModule,
    BrowserModule, // error gone when we add
    EcommerceRoutingModule
  ],
  bootstrap: [MainComponent],
})
export class EcommerceModule { }

Error: The selector app-main did not match any element

Error: The selector app-main did not match any element

Solution: check index.html add <app-main> and remove <app-root> to your html.

Code: index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>EcommerceAngular</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body class="mat-typography">
  <app-main></app-main>
  <!-- <app-root></app-root> -->
</body>
</html>
Run angular without error

That’s it. Now you can able to run without any error and we successfully create our module and make it as the main module.

I hope this will help you understand how the module works. Your comments are welcome!. Share the idea and get the idea. Have a great day.