Full Trust European Hosting

BLOG about Full Trust Hosting and Its Technology - Dedicated to European Windows Hosting Customer

AngularJS Hosting Europe - HostForLIFE :: Angular ngx-pagination Sample Implementation Step By Step Guide

clock September 5, 2022 08:41 by author Peter

Angular ngx-pagination Sample Implementation Step By Step Guide
In this example, I will show you how to implement ngx-pagination in your Angular Application.

ngx-pagination is the simplest pagination solution in Angular.

ngx-pagination also offers flexibility, responsiveness, and very handy customization.
I assumed that you have already installed Angular on your local machine. If not then here’s the link to basic Angular Installation.
    FYI: I’m a newbie in Angular I’m just enjoying documenting my journey in learning it.

Step 1: Create Angular Project

Create a new project called ngx-pagination-sample
ng new ngx-paging-sample
    Answer the 2 Angular CLI Questions:
    Would you like to add Angular routing? No
    Which stylesheet format whould you line to use? CSS

After installation, Navigate inside the project folder and open the application.
In my case, I Created a folder in drive: C called Angular and created the ngx-pagination-sample allication inside of it.
C:\Angular>cd ngx-pagination-sample
C:\Angular\ngx-paging-sample>code .


Step 2: Install ngx-pagination
Open Git Bash on your VS Code Terminal, Excecute the following command to add ngx-pagination
ng add ngx-pagination

OR
npm install ngx-pagination

The difference between ng add and npm install ng add, to look for the compatible version to install for your Angular Application while npm install installs the latest version of ngx-pagination which sometimes there are some incompatibility issues especially if you’re using an older version of Angular.

    If you’re using latest Angular Version then use npm install.

Step 3: Install Bootstrap for table and styles
    We need to install the Bootstrap UI package for styling the table and pagination.

Execute the following command:
npm install bootstrap

Go to the angular.json file and look for styles then add the following:
"./node_modules/bootstrap/dist/css/bootstrap.min.css"

Step 4: Setting up Data Model, Service, and Temporary Data
Go to app.module.ts and Import HttClientModule.

This module will help the service to fetch data from a third-party server but in our case, we’re going to use json file for our temporary data.
import { HttpClientModule } from ‘@angular/common/http’;
@NgModule({
    declarations: […],
    imports: [
        HttpClientModule
    ],
    bootstrap: […]
})
export class AppModule {}


Download Temporary Data customers.json then paste it inside your application assets folder.

Create a folder called _models

Inside of _models folder create an interface model called customer.model.ts
export interface Customer {
    id: number;
    firstName: string;
    lastName: string;
    birthday: Date;
    mobileNumber: string;
    email: string;
    createdOn: Date;
}

Inside of _models folder create an interface model called paging-config.model.ts
export interface PagingConfig {
    currentPage: number;
    itemsPerPage: number;
    totalItems: number;
}

Create a folder called _service and inside of it generate a data service called customer, you may create the service manually or type the following:
ng generate service customer

OR
ng g s customer

Add the code in customer.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Customer } from '../_models/customer.model';
@Injectable({
providedIn: 'root'
})
export class CustomerService {
    constructor(private httpClient: HttpClient) {}
    getCustomers(): Observable < Customer[] > {
        return this.httpClient.get < Customer[] > ("assets/customers.json");
    }
}

Step 5: Setting up Angular ngx-pagination
Implement PagingConfig on your AppComponent.ts and add initial values on the properties that will be implemented.

Code in the app.component.ts
import { Component } from '@angular/core';
import { Customer } from './_models/customer.model';
import { PagingConfig } from './_models/paging-config.model';
import { CustomerService } from './_services/customer.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements PagingConfig {
  title = 'ngx-paging-sample';

  currentPage:number  = 1;
  itemsPerPage: number = 5;
  totalItems: number = 0;

  tableSize: number[] = [5, 10, 15, 20];
  customers = new Array<Customer>();

  pagingConfig: PagingConfig = {} as PagingConfig;

  constructor(private customerService: CustomerService){
    this.getCustomers();

    this.pagingConfig = {
      itemsPerPage: this.itemsPerPage,
      currentPage: this.currentPage,
      totalItems: this.totalItems
    }
  }

  getCustomers(){
    this.customerService.getCustomers()
    .subscribe(res=> {
      this.customers = res;
      this.pagingConfig.totalItems = res.length;
    });
  }

  onTableDataChange(event:any){
    this.pagingConfig.currentPage  = event;
    this.getCustomers();
  }
  onTableSizeChange(event:any): void {
    this.pagingConfig.itemsPerPage = event.target.value;
    this.pagingConfig.currentPage = 1;
    this.getCustomers();
  }
}
    pagingConfig property is used for ngx-pagination paginate configuration.
    pagingConfig property will be instantiated inside the AppComponent constructor.

Add the HTML code on your app.component.html
<div class="container">
<div class="row justify-content-between">
  <div class="col-4">
    <h5 class="h3">NGX Pagination</h5>
  </div>
  <div class="col-2">
    <div class="row g-3 align-items-center">
      <div class="col-auto">
      <label class="control-label" for="noOfRows">No. of Rows</label>
    </div>
    <div class="col-auto">
      <select name="noOfRows" (change)="onTableSizeChange($event)" class="form-select form-select-sm">
        <option *ngFor="let size of tableSize" [ngValue]="size">
          {{ size }}
        </option>
      </select>
    </div>
  </div>
</div>
</div>
<br>
<table class="table  table-bordered">
  <thead class="table-dark">
    <tr>
      <th>Id</th>
      <th>Firt Name</th>
      <th>Last Name</th>
      <th>Birth Date</th>
      <th>Mobile Number</th>
      <th>Email</th>
      <th>Registration Date</th>
    </tr>
  </thead>
  <tr *ngFor="let customer of customers | paginate : pagingConfig; let i = index">
    <td>{{ customer.id }}</td>
    <td>{{ customer.firstName }}</td>
    <td>{{ customer.lastName }}</td>
    <td>{{ customer.birthday | date : 'MMMM dd,yyyy' }}</td>
    <td>{{ customer.mobileNumber }}</td>
    <td>{{ customer.email }}</td>
    <td>{{ customer.createdOn | date : 'MM/dd/yyyy' }}</td>
  </tr>
</table>
<div class="d-flex justify-content-center">
  <pagination-controls
  previousLabel="Prev"
  nextLabel="Next"
  (pageChange)="onTableDataChange($event)">
  </pagination-controls>
</div>
</div>


Run the application,
ng serve -o



AngularJS Hosting Europe - HostForLIFE :: How To Use Kendo UI In Angular Application?

clock September 1, 2022 07:26 by author Peter

Preconditions
    Basic knowledge of Angular CLI
    Bootstrap
    Node.js
    V.S. Code

We Covers the belowing things
    Create Angular application
    Create header,side menu and layout component with admin module.
    Angular Routing
    Kendo UI setup

Now let's use following command to create angular project,
ng new KendoUI
cd KendoUI

Now install bootstrap by using the following command,
npm install bootstrap --save

Now install KendoUI packages using following command,
npm install --save @progress/kendo-angular-charts @progress/kendo-angular-common @progress/kendo-angular-intl @progress/kendo-angular-l10n @progress/kendo-angular-popup @progress/kendo-drawing hammerjs @progress/kendo-licensing

Now install KendoUI theme using following command, I used default theme,
Default theme
npm install --save @progress/kendo-theme-default


Bootstrap theme
npm install --save @progress/kendo-theme-bootstrap

Material theme
npm install --save @progress/kendo-theme-material

Now Create the dashboard and layout component using the following command,
ng g c dashboard
ng g c layout

Now add the code in the following pages-:
Add this in app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { GridModule } from '@progress/kendo-angular-grid';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LayoutComponent } from './layout/layout.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { InputsModule } from '@progress/kendo-angular-inputs';
import { LabelModule } from '@progress/kendo-angular-label';
import { ChartsModule } from '@progress/kendo-angular-charts';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { DialogModule } from '@progress/kendo-angular-dialog';
import { UploadModule } from '@progress/kendo-angular-upload';
import { FileSelectModule } from '@progress/kendo-angular-upload';
import { PDFExportModule } from '@progress/kendo-angular-pdf-export';
import { NotificationModule } from '@progress/kendo-angular-notification';
import { NavigationModule } from '@progress/kendo-angular-navigation';
import { IconsModule } from '@progress/kendo-angular-icons';
import { IndicatorsModule } from '@progress/kendo-angular-indicators';
import { LayoutModule } from '@progress/kendo-angular-layout';

@NgModule({
  declarations: [
    AppComponent,
    LayoutComponent,
    DashboardComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    GridModule,
    BrowserAnimationsModule,
    InputsModule,
    LabelModule,
    ChartsModule,
    ButtonsModule,
    DialogModule,
    UploadModule,
    FileSelectModule,
    PDFExportModule,
    NotificationModule,
    NavigationModule,
    IconsModule,
    IndicatorsModule,
    LayoutModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


Add this in app.component.html
<router-outlet></router-outlet>

Add this in app-routing.module.ts
import {
    NgModule
} from '@angular/core';
import {
    RouterModule,
    Routes
} from '@angular/router';
import {
    DashboardComponent
} from './dashboard/dashboard.component';
import {
    LayoutComponent
} from './layout/layout.component';
const routes: Routes = [{
    path: 'Admin',
    component: LayoutComponent,
    children: [{
        path: 'Dashboard',
        component: DashboardComponent
    }]
}, {
    path: '**',
    redirectTo: "/Admin/Dashboard",
    pathMatch: 'full'
}, {
    path: '',
    redirectTo: "/Admin/Dashboard",
    pathMatch: 'full'
}];
@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule {}


Add this in layout.component.ts
import {
    Component,
    OnInit
} from '@angular/core';
@Component({
    selector: 'app-layout',
    templateUrl: './layout.component.html',
    styleUrls: ['./layout.component.css']
})
export class LayoutComponent implements OnInit {
    private data: any;
    public kendokaAvatar = '/assets/img/0.jpg';
    public logout = '/assets/img/logout.png';
    constructor() {}
    ngOnInit(): void {}
    public bottomNavigationItems: Array < any > = [{
        text: 'Home',
        icon: 'home',
        selected: true
    }, {
        text: 'Calendar',
        icon: 'calendar'
    }, {
        text: 'Notifications',
        icon: 'bell'
    }];
}


Add this in layout.component.html
<!--The content below is only a placeholder and can be replaced.-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="">
  <meta name="author" content="">
  <title>Kendo</title>
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<!-- <kendo-breadcrumb [items]="breadCrumbItems"></kendo-breadcrumb> -->
<!-- <kendo-bottomnavigation [border]="true" [items]="bottomNavigationItems"></kendo-bottomnavigation> -->
<br />
  <div id="wrapper">
    <!-- Navigation -->
    <nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
      <!-- <div class="navbar-header"> -->
        <!-- <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button> -->
        <!-- <a class="navbar-brand" href="index.html">Kendo Project</a> -->
      <!-- </div> -->
      <!-- /.navbar-header -->
      <!-- /.navbar-top-links -->
      <kendo-appbar position="top">
        <!-- <kendo-appbar-section>
            <button class="k-button k-button-clear">
                <kendo-icon name="menu"></kendo-icon>
            </button>
        </kendo-appbar-section> -->
        <!-- <kendo-appbar-section>
            <h1 class="title">Kendo Project</h1>
        </kendo-appbar-section> -->
        <kendo-appbar-spacer width="32px"></kendo-appbar-spacer>
        <kendo-appbar-section>
            <ul>
                <li><a class="DashFont" [routerLink]="['/Admin/Dashboard']">Dashboard</a></li>
                <!-- <li><a [routerLink]="['/Admin/userlist']">Users</a></li>
                <li><a [routerLink]="['/Admin/profile']">Profile</a></li>
                <li><a [routerLink]="['/Admin/userserver']">User List</a></li> -->
            </ul>
        </kendo-appbar-section>
        <kendo-appbar-spacer></kendo-appbar-spacer>
        <kendo-appbar-section>
          <a [routerLink]="['/Admin/profile']"><kendo-avatar [imageSrc]="kendokaAvatar" shape="circle" width="26px" height="26px"> </kendo-avatar></a>
        </kendo-appbar-section>
        <kendo-appbar-section class="actions">
          <a [routerLink]="['/AdminLogout']"><kendo-avatar [imageSrc]="logout" shape="circle" width="26px" height="26px"> </kendo-avatar></a>
            <kendo-badge-container>
                <button class="k-button k-button-clear">
                    <kendo-icon name="bell"></kendo-icon>
                </button>
                <kendo-badge shape="dot" themeColor="warning" size="small" position="inside"></kendo-badge>
            </kendo-badge-container>
            <span class="k-appbar-separator"></span>
        </kendo-appbar-section>
    </kendo-appbar>
      <!-- <div class="navbar-default sidebar" role="navigation">
        <div class="sidebar-nav navbar-collapse">
          <ul class="nav" id="side-menu">

            <li>
              <a [routerLink]="['/Admin/Dashboard']"><i class="fa fa-edit fa-fw"></i>Dashboard</a>
            </li>
            <li>
              <a [routerLink]="['/Admin/userlist']"><i class="fa fa-edit fa-fw"></i>Users List</a>
            </li>
            <li>
              <a [routerLink]="['/Admin/userserver']"><i class="fa fa-edit fa-fw"></i>Users Server List</a>
            </li>
            <li>
              <a [routerLink]="['/Admin/imagegrid']"><i class="fa fa-edit fa-fw"></i>Image Grid</a>
            </li>
            <li>
              <a [routerLink]="['/AdminLogout']"><i class="fa fa-edit fa-fw"></i>Logout</a>
            </li>
          </ul>
        </div>
      </div> -->
    </nav>
    <div id="page-wrapper">
      <div class="row">
        <div class="col-lg-12">
         <router-outlet></router-outlet>
        </div>
        <!-- /.col-lg-12 -->
      </div>
      <!-- /.row -->
    </div>
  </div>
  <!-- /#page-wrapper -->
  <!-- /#wrapper -->
</body>
</html>

Add this inlayout.component.css
: host {
    padding: 0;
}
kendo - appbar.title {
    font - size: 18 px;
    margin: 10 px;
}
kendo - badge - container {
    margin - right: 8 px;
}
kendo - appbar ul {
    font - size: 14 px;
    list - style - type: none;
    padding: 0;
    margin: 0;
    display: flex;
}
kendo - appbar li {
    margin: 0 9 px;
}
kendo - appbar li: hover {
    cursor: pointer;
    color: #d6002f;
}
kendo - appbar.actions.k - button {
    padding: 0;
}
kendo - breadcrumb {
    margin - left: 30 px;
}.DashFont {
    font - size: 16 px;
    font - family: 'Segoe UI', Tahoma, Geneva, Verdana, sans - serif;
}

Add this in dashboard.component.ts
import {
    Component,
    OnInit
} from '@angular/core';
@Component({
    selector: 'app-dashboard',
    templateUrl: './dashboard.component.html',
    styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
    ngOnInit(): void {}
    constructor() {}
    public events: string[] = [];
    public series: any[] = [{
        name: "India",
        data: [
            3.907, 7.943, 7.848, 9.284, 9.263, 9.801, 3.89, 8.238, 9.552, 6.855,
        ],
    }, {
        name: "Russian Federation",
        data: [4.743, 7.295, 7.175, 6.376, 8.153, 8.535, 5.247, -7.832, 4.3, 4.3],
    }, {
        name: "Germany",
        data: [
            0.01, -0.375, 1.161, 0.684, 3.7, 3.269, 1.083, -5.127, 3.69, 2.995,
        ],
    }, {
        name: "World",
        data: [
            1.988, 2.733, 3.994, 3.464, 4.001, 3.939, 1.333, -2.245, 4.339, 2.727,
        ],
    }, ];
    public categories: number[] = [
        2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
    ];
    public onRender(): void {
        this.log("render");
    }
    public onAxisLabelClick(e: any): void {
        this.log("axisLabelClick", e);
    }
    public onLegendItemClick(e: any): void {
        this.log("legendItemClick", e);
    }
    public onLegendItemHover(e: any): void {
        this.log("legendItemHover", e);
    }
    public onPlotAreaClick(e: any): void {
        this.log("plotAreaClick", e);
    }
    public onPlotAreaHover(e: any): void {
        this.log("plotAreaHover", e);
    }
    public onSeriesClick(e: any): void {
        this.log("seriesClick", e);
    }
    public onSeriesHover(e: any): void {
        this.log("seriesHover", e);
    }
    private log(event: string, arg: any = null): void {
        this.events.push(`${event}`);
        console.log(arg);
    }
    public data: any[] = [{
        kind: 'Hydroelectric',
        share: 0.175
    }, {
        kind: 'Nuclear',
        share: 0.238
    }, {
        kind: 'Coal',
        share: 0.118
    }, {
        kind: 'Solar',
        share: 0.052
    }, {
        kind: 'Wind',
        share: 0.225
    }, {
        kind: 'Other',
        share: 0.192
    }];
    public labelContent(e: any): string {
        return e.category;
    }
}


Add this in dashboard.component.html
<kendo-chart>
    <kendo-chart-title text="Units sold"></kendo-chart-title>
    <kendo-chart-category-axis>
        <kendo-chart-category-axis-item
            [categories]="['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'august' , 'september' , 'October', 'november', 'December']"
            [title]="{ text: 'Months' }">
        </kendo-chart-category-axis-item>
    </kendo-chart-category-axis>
    <kendo-chart-series-defaults [highlight]="{ inactiveOpacity: 0.3 }">
    </kendo-chart-series-defaults>
    <kendo-chart-series>
      <kendo-chart-series-item type="area" [data]="[123, 276, 310, 212, 240, 156, 98, 210, 200, 220, 180, 170]">
      </kendo-chart-series-item>
      <kendo-chart-series-item type="area" [data]="[165, 210, 287, 144, 190, 167, 212, 190, 210, 250, 260, 220]">
      </kendo-chart-series-item>
      <kendo-chart-series-item type="area" [data]="[56, 140, 195, 46, 123, 78, 95, 240, 250, 210, 280, 290, 320]">
      </kendo-chart-series-item>
    </kendo-chart-series>
  </kendo-chart>
<hr>
<kendo-chart>
    <kendo-chart-series>
      <kendo-chart-series-item
          type="donut" [data]="data"
          categoryField="kind" field="share">
        <kendo-chart-series-item-labels
          [content]="labelContent"
          color="#fff" background="none">
        </kendo-chart-series-item-labels>
      </kendo-chart-series-item>
    </kendo-chart-series>
    <kendo-chart-legend [visible]="false"></kendo-chart-legend>
  </kendo-chart>

JavaScript

Add this in package.json dependencies

"private": true,
  "dependencies": {
    "@angular/animations": "~12.1.0-",
    "@angular/common": "~12.1.0-",
    "@angular/compiler": "~12.1.0-",
    "@angular/core": "~12.1.0-",
    "@angular/forms": "~12.1.0-",
    "@angular/localize": "~12.1.0-",
    "@angular/platform-browser": "~12.1.0-",
    "@angular/platform-browser-dynamic": "~12.1.0-",
    "@angular/router": "~12.1.0-",
    "@progress/kendo-angular-buttons": "^7.0.0",
    "@progress/kendo-angular-charts": "^6.0.0",
    "@progress/kendo-angular-common": "^2.0.0",
    "@progress/kendo-angular-dateinputs": "^6.0.0",
    "@progress/kendo-angular-dialog": "^6.0.1",
    "@progress/kendo-angular-dropdowns": "^6.0.0",
    "@progress/kendo-angular-excel-export": "^4.0.0",
    "@progress/kendo-angular-grid": "^6.0.1",
    "@progress/kendo-angular-icons": "^1.0.0",
    "@progress/kendo-angular-indicators": "^1.1.2",
    "@progress/kendo-angular-inputs": "^8.0.0",
    "@progress/kendo-angular-intl": "^3.0.0",
    "@progress/kendo-angular-l10n": "^3.0.0",
    "@progress/kendo-angular-label": "^3.0.0",
    "@progress/kendo-angular-layout": "^6.5.0",
    "@progress/kendo-angular-navigation": "^1.1.4",
    "@progress/kendo-angular-notification": "^3.0.4",
    "@progress/kendo-angular-pdf-export": "^3.0.0",
    "@progress/kendo-angular-popup": "^4.0.3",
    "@progress/kendo-angular-progressbar": "^2.0.3",
    "@progress/kendo-angular-treeview": "^6.0.0",
    "@progress/kendo-angular-upload": "^8.0.0",
    "@progress/kendo-data-query": "^1.0.0",
    "@progress/kendo-drawing": "^1.0.0",
    "@progress/kendo-licensing": "^1.0.2",
    "@progress/kendo-svg-icons": "^0.1.2",
    "@progress/kendo-theme-default": "^5.0.0",
    "rxjs": "~6.6.0",
    "tslib": "^2.2.0",
    "zone.js": "~0.11.4"
  },

Now add the attached images

Now run the following command.
npm i

Now, please run the application using the 'npm start' command and check the result.



AngularJS Hosting Europe - HostForLIFE :: Async Validation In Angular

clock August 30, 2022 07:47 by author Peter

In this article, I will explain how to implement Async Validation In Angular. Angular does not provide built-in type async Validation implmentation, it provides only for sync validation. The implementation of async validator is very similar to the sync validator. The only difference is that the async Validators must return the result of the validation as an observable or as Promise. In this article, we will create an async validator for the Existing user. We will check the user exists or not using async validator.

Prerequisites
    Angular 12
    HTML/Bootstrap

For this article, I have created an Angular project using Angular 12. For creating an Angular project, we need to follow the following steps:

Create Project
I have created a project using the following command in the Command Prompt.
ng new AsyncValidatorExample

Open a project in Visual Studio Code using the following commands.
cd AsyncValidatorExample
Code .


Now in Visual Studio, your project looks like as below.


Rules for Async Validator
For creating an Async Validator there are following rules which need to be followed:
    The function must implement the AsyncValidatorFn Interface, which defines the signature of the validator function.
    The function should be returned in following observable or promise.
    If input is valid then must return null, or ValidationErrors if the input is invalid.

AsyncValidatorFn
AsyncValidatorFn is a predefine interface which defines the type of the validator function.

Signature of AsyncValidatorFn
interface AsyncValidatorFn {
  (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>
}

Let's create User Service that will check input user exists or not. For now, we will check it with local parameter not will API call.
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class UserService {
  private usernames = ['Gajendra', 'Rohit', 'Rohan', 'Ajay'];

  checkIfUsernameExists(value: string) {
    return of(this.usernames.some((a) => a.toLocaleUpperCase() === value.toLocaleUpperCase())).pipe(
      delay(1000)
    );
  }
}

Let's create Async Validator to check if the username exists against that method.
import {
  AbstractControl,
  AsyncValidatorFn,
  ValidationErrors,
} from '@angular/forms';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { UserService } from './user.service';

export class UsernameValidator {
  static createValidator(userService: UserService): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors> => {
      return userService
        .checkIfUsernameExists(control.value)
        .pipe(
          map((result: boolean) =>
            result ? { usernameAlreadyExists: true } : null
          )
        );
    };
  }
}


Use Of Async Validator

this.fb.group({
    username: [
      null,
      [UsernameValidator.createValidator(this.userService)],
      updateOn: 'blur'
    ],
  });


App.Component.ts
import { Component } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { UserService } from './user.service';
import { UsernameValidator } from './username-validator';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  constructor(private fb: FormBuilder, private userService: UserService) {}

  registrationForm = this.fb.group({
    username: [
      null,{
      asyncValidators:[UsernameValidator.createValidator(this.userService)],
      updateOn: 'blur'
}
    ],
  });
}


App.Component.html
<mat-form-field>
  <mat-label>Username</mat-label>
  <input matInput placeholder="Enter User Name here" formControlName="username" />
  <mat-error
    *ngIf="form.get('username').hasError('usernameAlreadyExists')"
  >
    Username already <strong>exists</strong>
  </mat-error>
</mat-form-field>

Let's Run the Project



European Visual Studio 2022 Hosting - HostForLIFE :: Error - PerfWatson2.exe Issue While Installing SSIS Projects In Visual Studio

clock August 23, 2022 07:07 by author Peter

Got the below error while installing the SQL Server Integration Services Projects for Visual Studio 2019.

Error
Please close following processes before continuing the setup:
PerfWatson2 (17784)

Followed the below steps and resolved the issue.

Step 1
Open the Task Manager and find for PerfWatson2.exe.

Step 2
Right Click on PerfWatson2.exe and Click on End task.


Issue is resolved and continue with the installation process.
Hope you have successfully resolved this issue.
Like and share your valuable feedback on this article.



AngularJS Hosting Europe - HostForLIFE :: Build Custom Audio Player With Audio Waveform In Angular

clock August 19, 2022 10:18 by author Peter

If you are working on a platform that needs to play some audio to a user, for example to sell an audio file, it's awesome to show its wave form. That way, the user will be impressed about the structure of the audio and of what your platform can do. To extract the information from the audio file, Web Audio API can be used. This allows you to extract frequency, waveform and other data from the audio file. Then, the received data from the audio source can be visualized as audio-waves. While dealing with the huge data that an audio waveform will have, drawing waveform smoothly and more quickly without lagging the web page is essential. As a developer, the performance of the page matters a lot, irrespective of the content shown on the page to the developer. So, I'm using CanvasJS chart to visualize the waveform. Note: CanvasJS can draw millions of datapoints in few milliseconds.


This tutorial shows how to create simple MP3 player using web audio API, and how to visualize audio files using CanvasJS. The underlying techniques work within plain JavaScript, Angular, React or any other JavaScript framework. In this case, I'm using Angular to create waveforms.

Browse & Read Audio File
The first step to play audio and visualize waveforms is to get the audio file. Let's add an input field to accept MP3 files. Here I've restricted it to allow the user to browse just MP3 files. However, web audio API supports WAV, MP3, AAC, OGG and other formats.
<input type="file" class="file-input"
       accept="audio/mp3"
       change)="onFileSelected($event)" #fileUpload>


Read Audio File
To fetch audio using the Web Audio API, we need to get an ArrayBuffer of audio data and pass it to a BufferSource. To get an audio buffer of the sound, you need to use the AudioContext.decodeAudioData method. The decoded AudioBuffer is resampled to the AudioContext's sampling rate, then passed to a callback or promise.
let margin = 10,
    chunkSize = 50,
    scaleFactor = (150 - margin * 2) / 2;
let audioContext = new AudioContext(),
    buffer = await file.arrayBuffer(),
    audioBuffer = await audioContext.decodeAudioData(buffer),
    float32Array = audioBuffer.getChannelData(0);
let array = [],
    i = 0,
    length = float32Array.length;
while (i < length) {
    array.push(float32Array.slice(i, i += chunkSize).reduce(function(total, value) {
        return Math.max(total, Math.abs(value));
    }));
}

Add Play / Pause & Stop Buttons
Add two buttons, one for play/pause and another to stop. When the audio is playing, the icon should show what the user can do by clicking that button. So, it will show the "Pause" icon when the audio is playing and "Play" icon when the audio is paused. To do this, we need to toggle between the play and pause states. In Web Audio API, you can check for the state of the audio-context, and based on the current state either resume the audio or suspend it.
togglePlaying = (event: any) => {
    if(audioContext.state === 'running') {
        audioContext.suspend().then(() => {
          buttonStatus = "Play";
        });
    }
    else if(audioContext.state === 'suspended') {
        audioContext.resume().then(() => {
          buttonStatus = "Pause";
        });
    }
}

When it comes to the stop option, this is pretty simple. Web Audio API has option to stop the source by calling stop() method.
stopPlaying = (event: any) => {
    source.stop();
}


Generate Datapoints from the Audio Data
CanvasJS supports varieties of chart types for different sets of data, including line, area, pie, range, and financial charts, etc. For our case, range-area suits well - it looks like audio waves. The only task for us to do is to generate datapoints, pass it to datapoints and call chart.render(). CanvasJS draws wave graphs like a charm.
let dps = []
for (let index in array) {
    dps.push({ x: margin + Number(index), y: [50 - array[index] * scaleFactor, 50 + array[index] * scaleFactor]});
}

this.chart.options.data[0].dataPoints = dps;
this.chart.render();


Add Audio Playing Effect to the Wave

When audio begins playing, it is an excellent idea to shade the region that has already played in the waveform. Add a stripline to show the shaded region in the chart and keep updating it every few milliseconds or second. Stop updating it once the audio stops playing.
source.onended = () => {
    chart.axisX[0].stripLines[0].set("endValue", chart.axisX[0].get("maximum"));
    clearInterval(intervalId);
}
let intervalId = setInterval(() => {
    chart.axisX[0].stripLines[0].set("endValue", audioContext.currentTime * (chart.data[0].dataPoints.length / audioBuffer.duration));
}, 250);


Yippee! You just built a custom audio player with play, pause and stop options, along with the audio waveform generated using CanvasJS range-area chart. You can also use column chart, range-column chart to show waves differently. You can even customize the look and feel of the audio player using simple CSS properties, and can match the same with the waveform by changing CanvasJS chart properties.

This waveform generated by CanvasJS chart can be integrated with an audio/video player to make it more appealing to the user. Library has more customization options to change the look and feel, which gives you more flexibility to customize the chart look and feel to match with your website/player theme. In this tutorial, I have disabled chart interactivity so as to showcase only the waveform. However, CanvasJS supports interactivity where it shows tooltip and highlights when you hover over the chart.



European Visual Studio 2022 Hosting - HostForLIFE :: Automating NuGet Package Uploads

clock August 9, 2022 07:44 by author Peter

The Challenge
When maintaining a larger number of NuGet packages, updating to a new version can become a tedious task. You need to upload all new packages, if there are dependencies between the different packages you also need to be fast in order to avoid breaking your packages. However, this task can also be automated - here's how.

Creating an API key
First of all, you need to create an API key that allows to push new packages to the NuGet server. Once logged in, you can choose the corresponding menu from here:

On the following page you can then choose the key name, the actions available for this key and the packages this key should apply to. In this example, I've used a global pattern to allow uploading all packages starting with combit.ListLabel:


After clicking "Create" you'll have the only chance ever to copy/view the generated key - make sure to use this opportunity wisely. Also, note that keys do have an expiration date. After this, you need to regenerate the key.


Using the Key for Automated Uploads
The next step is to use this key for an automated upload, of course. We've created a rather sophisticated batch file for this purpose which I'm sharing here. All required input is queried from the user. As the owner of this batch file may upload any packages on your behalf, make sure to store it in a very secure path only. The nuget push is repeated for each applicable package at the end.

@ECHO OFF

REM ==================================================================================================================================================
REM CONFIGURATION BEGIN
REM DO NOT EDIT BEFORE THIS LINE!
REM ==================================================================================================================================================
SET MajorVersion=27

SET NuGetExePath=.\nuget.exe

SET ApiKey=<Your API key>
SET Server=https://api.nuget.org/v3/index.json

REM ==================================================================================================================================================
REM CONFIGURATION END
REM DO NOT EDIT AFTER THIS LINE!
REM ==================================================================================================================================================

ECHO INFO: The NuGet version must match the format "Major.Minor.Patch[-Suffix]" (see examples):
ECHO    27.0.0-alpha1
ECHO    27.0.0-beta1
ECHO    27.0.0-beta2
ECHO    27.1.0
ECHO    27.2.1

SET NugetVersionString=%MajorVersion%

:UserPrompt_PrereleaseVersion
ECHO.
SET "UserChoice_PrereleaseVersion="
SET /P "UserChoice_PrereleaseVersion=Enter Pre-release version (values: "alpha" or "beta" without quotes; press 'Enter' to proceed without Pre-release version): %NugetVersionString%.0.0-"

IF /I "%UserChoice_PrereleaseVersion%" == "" (
    GOTO UserPrompt_MinorVersion
) ELSE (
    SET NugetVersionString=%NugetVersionString%.0.0-%UserChoice_PrereleaseVersion%
    GOTO UserPrompt_PrereleaseVersionSuffix
)

:UserPrompt_PrereleaseVersionSuffix
ECHO.
SET "UserChoice_PrereleaseVersionSuffix="
SET /P "UserChoice_PrereleaseVersionSuffix=Enter Pre-release version suffix (values: "2" and higher without quotes; press 'Enter' to proceed with Pre-release suffix default "1"): %NugetVersionString%"

IF /I "%UserChoice_PrereleaseVersionSuffix%" == "" (
    SET NugetVersionString=%NugetVersionString%1
) ELSE (
    SET NugetVersionString=%NugetVersionString%%UserChoice_PrereleaseVersionSuffix%
)

GOTO UserPrompt_FinalWarning

:UserPrompt_MinorVersion
ECHO.
SET "UserChoice_MinorVersion="
SET /P "UserChoice_MinorVersion=Enter Minor version (values: "1" or higher without quotes; press 'Enter' to proceed with default "0"): %NugetVersionString%."

IF /I "%UserChoice_MinorVersion%" == "" (
    SET NugetVersionString=%NugetVersionString%.0
) ELSE (
    SET NugetVersionString=%NugetVersionString%.%UserChoice_MinorVersion%
)

GOTO UserPrompt_PatchVersion

:UserPrompt_PatchVersion
ECHO.
SET "UserChoice_PatchVersion="
SET /P "UserChoice_PatchVersion=Enter Patch version (values: "1" or higher without quotes; press 'Enter' to proceed with default "0"): %NugetVersionString%."

IF /I "%UserChoice_PatchVersion%" == "" (
    SET NugetVersionString=%NugetVersionString%.0
) ELSE (
    SET NugetVersionString=%NugetVersionString%.%UserChoice_PatchVersion%
)

GOTO UserPrompt_FinalWarning

:UserPrompt_FinalWarning
ECHO.
IF /I NOT "%UserChoice_PrereleaseVersion%" == "" (
    SET PackageSourcePath=\\srvchk\prod\LL%MajorVersion%\%UserChoice_PrereleaseVersion%%UserChoice_PrereleaseVersionSuffix%\NuGet
) ELSE (
    SET PackageSourcePath=\\srvchk\prod\LL%MajorVersion%\Release\%MajorVersion%.00%UserChoice_MinorVersion%\NuGet
)

SETLOCAL EnableExtensions EnableDelayedExpansion
SET "UserChoice_FinalWarning=N"
SET /P "UserChoice_FinalWarning=WARNING: This cannot be undone. Really upload NuGet packages for version "%NugetVersionString%" ("%PackageSourcePath%") [Y/N]? "
SET "UserChoice_FinalWarning=!UserChoice_FinalWarning: =!"

IF /I "!UserChoice_FinalWarning!" == "N" ENDLOCAL & GOTO :EOF
IF /I NOT "!UserChoice_FinalWarning!" == "Y" GOTO UserPrompt_FinalWarning

ENDLOCAL
GOTO Upload

:Upload
REM Push packages to server
ECHO.
ECHO Uploading packages...
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.AdhocDesign.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.AdhocDesign.Web.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.CassandraDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.FirebirdConnectionDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.MongoDBDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.MySqlConnectionDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.NpgsqlConnectionDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.NuoDbConnectionDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.OdbcConnectionDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.OleDbConnectionDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.RedisDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.ReportServerIntegration.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.SalesforceDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.SqlConnectionDataProvider.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.Web.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ListLabel%MajorVersion%.Wpf.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ReportServer%MajorVersion%.ClientApi.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%
%NuGetExePath% push "%PackageSourcePath%\combit.ReportServer%MajorVersion%.SharedTypes.%NugetVersionString%.nupkg" -ApiKey %ApiKey% -Source %Server%

PAUSE


The Result
Once executed, the package is uploaded and shows up with the newly created version. The result looks just like a "normal" upload, but the process is much less error prone and executed in a matter of seconds:


Wrapping Up
The presented batch file allows to automate the management of larger NuGet package zoos. We're using it successfully to maintain our roundabout 50 packages with 87k downloads on nuget.org. It will be a great help for others facing the same challenges.



AngularJS Hosting Europe - HostForLIFE :: How To Add Charts In Angular Material Components?

clock August 5, 2022 09:53 by author Peter

Angular Material is a UI component library based on material design, the UI standard developed by Google, that provides clean and intuitive components. Components can be easily integrated with angular apps, which helps in achieving elegant and consistent UI. You can also create beautiful dashboards using these components.

Dashboards generally contain charts representing useful data to make analysis easier. In this article, I will guide how to add charts in the material tab component. I will be using CanvasJS angular chart component, which supports 30+ chart types, like line, column, bar, pie, etc. This also makes our life easier using its simple API to customize the look and feel of the chart. It also comes with various features, like zooming, panning, export chart as image, etc. out of the box.

 

Steps By Steps Instructions
Step 1

Create a simple angular application using angular cli command. If you have already set up the angular application, you can skip this step.
ng new angular-charts-in-material-component

Step 2
Now, navigate to the project directory and install angular material using ng add command. This will also install Component Dev Kit(CDK), Animation Module. To make it simple, I will be using predefined themes and will enable BrowserAnimationModule.
ng add @angular/material

Step 3
Register and import the components in app.module.ts. In this tutorial, I will be using Material Tab Component (MatTabsModule). You can use other material components like dialog, expansion panel, etc. as per your needs.
import { MatTabsModule } from '@angular/material/tabs';
@NgModule({
    declarations: [
        AppComponent,
    ],
    imports: [..
        MatTabsModule.
    ],
    providers: [],
    bootstrap: [AppComponent]
})

Step 4
Now, we will add Material Tabs to the template file app.component.html. Add matTabContent directive attribute to each tab body so that content is shown only when it becomes active.
<div [@.disabled]="true">
  <mat-tab-group dynamicHeight>
    <mat-tab label="Column Chart">
    <ng-template matTabContent>
    </ng-template>
  </mat-tab>
  <mat-tab label="Pie Chart">
     <ng-template matTabContent>
     </ng-template>
  </mat-tab>
  <mat-tab label="Line Chart">
     <ng-template matTabContent>
     </ng-template>
   </mat-tab>
 </mat-tab-group>
</div>

Step 5
After adding tabs to the application, we will now add charts to individual tabs. Before doing that, we will need to install CanvasJS angular chart component and register it. Please refer to this tutorial for basic setup of chart components. After installing the chart components, we will define chart options for different charts to be shown inside individual tabs in our app.component.ts.
export class AppComponent {
    columnChartOptions = {
        animationEnabled: true,
        title: {
        text: 'Angular Column Chart in Material UI Tabs',
        },
        data: [
        {
            // Change type to "doughnut", "line", "splineArea", etc.
            type: 'column',
            dataPoints: [
            { label: 'apple', y: 10 },
            { label: 'orange', y: 15 },
            { label: 'banana', y: 25 },
            { label: 'mango', y: 30 },
            { label: 'grape', y: 28 },
            ],
        },
        ],
    };

    pieChartOptions = {
        animationEnabled: true,
        title: {
        text: 'Angular Pie Chart in Material UI Tabs',
        },
        theme: 'light2', // "light1", "dark1", "dark2"
        data: [
        {
            type: 'pie',
            dataPoints: [
            { label: 'apple', y: 10 },
            { label: 'orange', y: 15 },
            { label: 'banana', y: 25 },
            { label: 'mango', y: 30 },
            { label: 'grape', y: 28 },
            ],
        },
        ],
    };

    lineChartOptions = {
        animationEnabled: true,
        title: {
        text: 'Angular Line Chart in Material UI Tabs',
        },
        theme: 'light2', // "light1", "dark1", "dark2"
        data: [
        {
            type: 'line',
            dataPoints: [
            { label: 'apple', y: 10 },
            { label: 'orange', y: 15 },
            { label: 'banana', y: 25 },
            { label: 'mango', y: 30 },
            { label: 'grape', y: 28 },
            ],
        },
        ],
    };
}

Step 6
After adding the chart component, we will add the canvasjs-chart directive inside individual tab content with respective chart options defined in app.component.ts.
<div [@.disabled]="true">
<mat-tab-group>
  <mat-tab label="Column Chart">
    <ng-template matTabContent>
      <canvasjs-chart
        [options]="columnChartOptions"
        [styles]="{ width: '100%', height: '360px' }"
      ></canvasjs-chart>
    </ng-template>
  </mat-tab>
  <mat-tab label="Pie Chart">
    <ng-template matTabContent>
      <canvasjs-chart
        [options]="pieChartOptions"
        [styles]="{ width: '100%', height: '360px' }"
      ></canvasjs-chart>
    </ng-template>
  </mat-tab>
  <mat-tab label="Line Chart">
    <ng-template matTabContent>
      <canvasjs-chart
        [options]="lineChartOptions"
        [styles]="{ width: '100%', height: '360px' }"
      ></canvasjs-chart>
    </ng-template>
  </mat-tab>
</mat-tab-group>
</div>


Ta-da! We have successfully plotted a chart inside angular material tabs. Please check out this StackBlitz example for the complete working code.

To take this article to the next step, you can alos add charts inside different angular material components, like dialog, expansion panel, cards, etc. and create beautiful dashboards using it.

You can refer to this link if you want to know more about the other components in angular material. Also, check out this link if you are new to CanvasJS angular chart component and want to explore more about its customization and features.



Node.js Hosting Europe - HostForLIFE :: Difference Between Node Cache And Redis Cache

clock July 26, 2022 10:15 by author Peter

What is Caching and why it is required?
When the same response needs to be served multiple times, store the data in a temporary memory cache and it can be retrieved faster than the data retrieved from the storage layer for every single call. Caching is an ability of an application to duplicate the values for a specified period of time and serve the web request instantly.


These techniques will be effective when
    There is a need to call for a 3rd party API and the call counts
    Cost of data transfer between cloud and the server.
    Server response is critical based on the concurrent requests.

Types of server caching available in Node JS
    In-app memory Cache
    Distributed Cache

In-app memory Cache

Data storage and retrieval will be in the process of the app memory cache. In-app caching is achieved through NodeJS packages such as node-cache, memory-cache, api-cache, etc.,


Distributed Cache
Data storage and retrieval will be carried out in centralized distributed systems. Though many options are available in this category the most popular ones are Redis and Memcached.


Other aspects of these cache techniques
In the Node Cache, the cached data are accessible only in the current process. If there is a cluster deployed with load balancer then multiple caches need to be stored which leads to constant updating of the data in every system or otherwise the user fetches the wrong information.

Also, if the stored cache is not properly maintained it may result in out of memory failures since the same memory space is utilized. On the other hand if the application is restarted the cached data will be disposed.

Redis can handle the above limitations easily, still it increases the dependency of the system. And that system needs to be monitored constantly not only for the availability but also for the performance degradations, outages.

Though Redis offers features like replication, level of durability, clustering and high availability (HA) but simple node-cache will be easy if the application needs to be scaled up and down easily and quickly.

Static information stored in cache does not require a network call dependency. Node cache is faster to store and retrieve data with a TTL (Time To Live).

Things to consider before choosing the right Caching technique:
    Security risks for storing and retaining the data in the cache.
    Data object serialization is really required for storing the data.
    Prevention of App crash by handling cache failures due to memory leaks or unavailability.
    Policy creation for cache maximum size, expiration of the cached memory, frequency of writing data to cache.
    Calculating the advantages of using cached data for the application.

 



AngularJS Hosting Europe - HostForLIFE :: Angular HTTP (Web API Integration)

clock July 18, 2022 10:42 by author Peter

HttpClient is used to make HTTP requests like GET | POST | PUT | DELETE to back end server.


The Angular HTTP client module is firstly introduced in the Angular 4.3 version.

This new API is available in the package @angular/common/http. This is a replacement for the old HttpModule.

The HTTP Client makes use of the RxJs Observables. The Response from the HttpClient Is observable, hence it needs to be Subscribed.

Import HttpClient Module in Root Module

STEP 1
The first thing is to import the HttpClientModule in app.module.ts
import {
    HttpClientModule
} from '@angular/common/http';
imports: [
    HttpClientModule
],


Import Required Module in Component/Service and then Inject HttpClient service
import {
    HttpClient
} from '@angular/common/http';
constructor(public http: HttpClient) {}


STEP 2
Define your base URL of API and inject the HttpClient in service constructor then define your GET/POST/PUT/DELETE calls as shown below
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import {  Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { User } from '../User';

@Injectable({
  providedIn: 'root'
})
export class UserService {
    private apiURL = "http://localhost:56299/api/"; //YOUR API URL
    httpOptions = {
        headers: new HttpHeaders({
            'Content-Type': 'application/json'
        })
    }
    constructor(private httpClient: HttpClient) {}
    getUsers(): Observable < User[] > {
        return this.httpClient.get < User[] > (this.apiURL + 'userapi/').pipe(catchError(this.errorHandler));
    }
    addUser(user: User): Observable < User > {
        return this.httpClient.post < User > (this.apiURL + 'userapi/', JSON.stringify(user), this.httpOptions).pipe(catchError(this.errorHandler))
    }
    getUsersByID(id: number): Observable < User > {
        return this.httpClient.get < User > (this.apiURL + '/userapi/' + id).pipe(catchError(this.errorHandler))
    }
    updateUser(user: User): Observable < User > {
        return this.httpClient.put < User > (this.apiURL + '/userapi/' + user.id, JSON.stringify(user), this.httpOptions).pipe(catchError(this.errorHandler))
    }
    removeUser(id: number) {
        return this.httpClient.delete < User > (this.apiURL + 'userapi/' + id, this.httpOptions).pipe(catchError(this.errorHandler));
    }
    errorHandler(error: {
        error: {
            message: string;
        };status: any;message: any;
    }) {
        let errorMessage = '';
        if (error.error instanceof ErrorEvent) {
            errorMessage = error.error.message;
        } else {
            errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
        }
        return throwError(errorMessage);
    }
}


STEP 3
In your component file subscribe to the service to get the response
//GET
this.userService.getUsers().subscribe((data: User[]) => {
    this.userList = data;
});
//DELETE
this.userService.removeUser(id).subscribe(() => {
    this.refreshUser();
});
//POST
this.userService.addUser(this.userform.value).subscribe((data: User) => {
    //Redirecting to user List page after save or update
    this.router.navigate(['/user']);
});
//PUT
this.userService.updateUser(this.userform.value).subscribe((data: User) => {
    //Redirecting to user List page after save or update
    this.router.navigate(['/user']);
});



AngularJS Hosting Europe - HostForLIFE :: Angular Forms

clock July 13, 2022 08:43 by author Peter

User INPUT data are collected using Angular forms.

There are two approaches by which we can create forms in angular.
    Template Driven Forms
    Model Driven Forms

1. TEMPLATE DRIVEN FORMS
First, we build a simple Contact form. The ngForm directive will convert it to the Template-driven form and create the top-level FormGroup control.\
Next, we use the ngModel directive to create the FormControl instance for each of the HTML form elements.
<form #contactForm="ngForm" (ngSubmit)="onSubmit(contactForm)">
  <h1 class="text-center"> <strong> ANGULAR TEMPLATE DRIVEN FORM DEMO</strong></h1>
  <br>
  <div class="container">
    <div class="row">
      <div class="col-md-6">
        <div class="mb-1">
          <label class="form-label" for="firstname">First Name</label>
          <div class="input-group">
            <input type="text" class="form-control" name="firstname" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="lastname">Last Name</label>
          <div class="input-group">
            <input type="text"  class="form-control" name="lastname" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="email">Email </label>
          <div class="input-group">
            <input type="text" class="form-control" id="email" name="email" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="gender">Geneder</label>
          <div class="input-group">
            <input type="radio" value="male" name="gender" ngModel> Male
            <input type="radio" value="female" name="gender" ngModel> Female
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="isMarried">Married</label>
          <div class="input-group">
            <input type="checkbox" name="isMarried" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="country">Country</label>

          <div class="input-group">
            <select name="country"  class="form-control" ngModel>
              <option [ngValue]="c.id" *ngFor="let c of countryList">
                {{c.name}}
              </option>
            </select>
          </div>
        </div>
        <div ngModelGroup="address">
          <div class="mb-1">
            <label class="form-label" for="city">City</label>
            <div class="input-group">
              <input type="text" class="form-control" name="city" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <label class="form-label" for="street">Street</label>
            <div class="input-group">
              <input type="text" class="form-control" name="street" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <label class="form-label" for="pincode">Pin Code</label>
            <div class="input-group">
              <input class="form-label" class="form-control" type="text" name="pincode" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <div class="input-group">
              <button class="btn btn-primary" type="submit">Submit</button>
            </div>
          </div>

      </div>
      </div>
      <div class="col-md-6">
        <pre>Value : {{contactForm.value | json }} </pre>
        <pre>Valid : {{contactForm.valid}} </pre>
        <pre>Touched : {{contactForm.touched  }} </pre>
        <pre>Submitted : {{contactForm.submitted  }} </pre>
      </div>
    </div>
  </div>
  </form>


Next, we will submit the form data to the component class.
import { Component, OnInit } from '@angular/core';
export class country {
  id:string;
  name:string;

  constructor(id:string, name:string) {
    this.id=id;
    this.name=name;
  }
}
@Component({
  selector: 'app-templatedrivenform',
  templateUrl: './templatedrivenform.component.html',
  styleUrls: ['./templatedrivenform.component.css']
})
export class TemplatedrivenformComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }
  countryList:country[] = [
    new country("1", "India"),
    new country('2', 'USA'),
    new country('3', 'England')
  ];
  onSubmit(contactForm: { value: any; }) {
    console.log(contactForm.value);
  }

}

OUTPUT


2. MODEL DRIVEN FORMS (REACTIVE FORMS)
In Reactive forms we define the structure of the form in the component class. i.e. We define the form model with Form Groups, Form Control and Form Arrays. And then we define validation rules in the component class. And finally, we bind it to the HTML form in the template.
How to use Reactive Forms

    Import ReactiveFormsModule
    Defining Form Model in the component
    Create the HTML Form uses the Form Model properties.Bind the HTML Form to the Form Model

1. Import ReactiveFormsModule
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

 imports: [

     //  Angular Form Modules
    FormsModule,
    ReactiveFormsModule
  ],


2. Defining Form Model in the component
FormGroup Represents a collection of form controls. It can also contain other Form Groups and FormArrays. In fact, an angular form is a FormGroup.

FormControl Encapsulates the state of a single form element in our form. It stores the value and state of the form element and helps us to interact with them using properties & methods.
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from '../service/user.service';

@Component({
  selector: 'app-add-user',
  templateUrl: './add-user.component.html',
  styleUrls: ['./add-user.component.css']
})
export class AddUserComponent implements OnInit {

  id: number = 0;
  userform: FormGroup;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private fb: FormBuilder,
    private userService: UserService
  ) {
    //**************Create Reactive Form with validation********************* */
    this.userform = this.fb.group({
      name: ['', [Validators.required]],
      mobile: ['', []],
      email: ['', [Validators.required, Validators.email, Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$')]],
      gender: ['', [Validators.required]],
      dob: [null, [Validators.required]],
      id: [0, [Validators.required]],
      isActive: [true],
      rating: [0, []],
      userType: ['', [Validators.required]],
    });

  }

  ngOnInit(): void {
    //**************Get User ID On Edit********************* */
    this.route.params.subscribe(params => {
      this.id = params['id'];
      if (params['id'] != null) {
        this.userform.get('Id')?.setValue(params['id']);
        const data = this.userService.getUsersByID(this.id);
        if (data) {
          this.userform.setValue(data);
        }
      }
    });
  }

  save() {
    if (this.userform.invalid) // true if any form validation fail
      return

    if (this.userform.get('id')?.value === 0) {
      // on Create New User
      this.userService.addUser(this.userform.value);
    } else {
      // on Update User info
      this.userService.updateUser(this.userform.value);
    }

    //Redirecting to user List page after save or update
    this.router.navigate(['/user']);
  }

}


3. User Form
<div class="container">
  <form [formGroup]="userform" autocomplete="off">
      <div class="mb-1">
          <label for="name" class="form-label">Name</label>
          <div class="input-group has-validation">
              <input type="text" #name [ngClass]="{'form-control': true, 'is-invalid': userform.get('name')?.invalid &&
              (userform.get('name')?.dirty || userform.get('name')?.touched)}" id="name" name="name"
                  formControlName="name" placeholder="Name">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="mobile" class="form-label">Mobile</label>
          <div class="input-group has-validation">
              <input type="number" maxlength="10" [ngClass]="{'form-control': true, 'is-invalid': userform.get('mobile')?.invalid &&
              (userform.get('mobile')?.dirty || userform.get('mobile')?.touched)}" id="mobile" name="mobile"
                  formControlName="mobile" placeholder="Mobile">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="rating" class="form-label">Rating</label>
          <div class="input-group has-validation">
            <input type="number" maxlength="10" [ngClass]="{'form-control': true, 'is-invalid': userform.get('rating')?.invalid &&
            (userform.get('rating')?.dirty || userform.get('rating')?.touched)}" id="rating" name="rating"
                formControlName="rating" placeholder="rating">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="email" class="form-label">Email</label>
          <div class="input-group has-validation">
              <input type="email" [ngClass]="{'form-control': true, 'is-invalid': userform.get('email')?.invalid &&
                  (userform.get('email')?.dirty || userform.get('email')?.touched)}" id="email" name="email"
                  formControlName="email" placeholder="[email protected]">
              <div class="invalid-feedback">
                  {{userform.get('email')?.hasError('required') ? 'This field is required.':'Invalid Email'}}
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="DOB" class="form-label">DOB</label>
          <input type="date" [ngClass]="{'form-control': true, 'is-invalid': userform.get('dob')?.invalid &&
                  (userform.get('dob')?.dirty || userform.get('dob')?.touched)}" id="dob" name="dob"
                  formControlName="dob">
      </div>
      <div class="mb-1">
          <label for="email" class="form-label">Gender {{userform.get('gender')?.value}} </label>
          <div class="input-group has-validation">
              <select [ngClass]="{'form-select': true, 'is-invalid': userform.get('gender')?.invalid &&
                  (userform.get('gender')?.dirty || userform.get('gender')?.touched)}"
                  aria-label="Default select example" formControlName="gender">
                  <option value=""> --Select--</option>
                  <option value="Male" selected="userform.get('gender')?.value=='Male'">Male</option>
                  <option value="Female" selected="userform.get('gender')?.value=='Female'">Female</option>
              </select>
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="name" class="form-label">User Type</label>
          <div class="input-group has-validation">
              <div class="form-check form-check-inline">
                  <input class="form-check-input" formControlName="userType" type="radio" id="User" value="User">
                  <label class="form-check-label" for="User">User</label>
              </div>
              <div class="form-check form-check-inline">
                  <input class="form-check-input" formControlName="userType" type="radio" id="Admin" value="Admin">
                  <label class="form-check-label" for="Admin">Admin</label>
              </div>
          </div>
      </div>
      <div class="mb-1">
          <div class="form-check form-switch">
              <input class="form-check-input" type="checkbox" formControlName="isActive" id="isActive">
              <label class="form-check-label" for="isActive">Is Active</label>
          </div>
      </div>
      <div class="mb-1">
          <div class="btn-group" role="group" aria-label="Basic example">
              <button (click)="save()" [disabled]="userform.invalid" class="btn btn-primary" type="button">
                  {{id==0 || id==null ?'Save':'Update'}}</button>
              <button class="btn btn-secondary" type="button">Reset </button>
          </div>
      </div>

      <div class="mb-1">
          {{userform.value |json}}
      </div>
  </form>
</div>

OUTPUT

 



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in