CURD Operation Using KendoUI In Angular With .NET Core API Using Dapper And Angular Routing

Introduction

KendoUI is a UI framework that has 100+ angular UI widgets and features. Using KendoUI it is easy to create an application by using KendoUI widgets. We are here to perform CURD operations using KendoUI. Here we also learn image upload using angular and .Net Core API.

We already created an API in the previous article that we need in this article. Below is the link for the API.

Preconditions

  • Basic knowledge of Angular CLI
  • Basic knowledge of .Net core
  • Basic knowledge of SQL Server
  • Bootstrap
  • Node.js
  • V.S. Code,Visual Studio

We cover the below things,

  • Create Angular application
  • Angular Routing
  • Kendo UI setup
  • KendoUI CURD Operation
  • Image Upload

Step 1

Run the below command in cmd for creating new angular project.

ng new KendoGridProject

Step 2

Now create the following file according to the below image

Step 3

Add the following code in package.json,

{
    "name": "kendo-ui",
    "version": "0.0.0",
    "scripts": {
      "ng": "ng",
      "start": "ng serve",
      "build": "ng build",
      "watch": "ng build --watch --configuration development",
      "test": "ng test"
    },
    "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.3",
      "@progress/kendo-angular-icons": "^1.0.0",
      "@progress/kendo-angular-indicators": "^1.1.2",
      "@progress/kendo-angular-inputs": "^8.0.5",
      "@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.2.2",
      "@progress/kendo-svg-icons": "^0.1.2",
      "@progress/kendo-theme-default": "^5.0.0",
      "hammerjs": "^2.0.8",
      "rxjs": "~6.6.0",
      "tslib": "^2.2.0",
      "zone.js": "~0.11.4"
    },
    "devDependencies": {
      "@angular-devkit/build-angular": "~12.1.3",
      "@angular/cli": "~12.1.3",
      "@angular/compiler-cli": "~12.1.0-",
      "@types/jasmine": "~3.8.0",
      "@types/node": "^12.20.46",
      "jasmine-core": "~3.8.0",
      "karma": "^6.3.16",
      "karma-chrome-launcher": "~3.1.0",
      "karma-coverage": "~2.0.3",
      "karma-jasmine": "~4.0.0",
      "karma-jasmine-html-reporter": "~1.7.0",
      "typescript": "~4.3.2"
   }
}

Now run the following command in cmd,

npm i

Step 4

Add the following code in layout.component.html,


<!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>
<br />
  <div id="wrapper">
    <!-- Navigation -->
    <nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
      <kendo-appbar position="top">
        <kendo-appbar-spacer width="32px"></kendo-appbar-spacer>
        <kendo-appbar-section>
            <ul>
                <li><a class="DashFont" [routerLink]="['/Admin/Dashboard']">Dashboard</a></li>
               <li><a class="DashFont" [routerLink]="['/Admin/UserList']">Users</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>
    </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>

Step 5

Add the following code 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'}
  ];
}

Step 6

Add the following code in environment.ts

export const environment = 
{
    production: false,
    apiEndpoint: 'http://localhost:49749'
  };

Step 7

Add the following code in app.UserModel.ts,

Step 8

Add the following code in app.UserModelss.ts,

export class  UserModel 
{
        public UserId: number =0;
        public UserName: string =""; 
        public FullName: string ="";
        public EmailId: string ="";
        public Contactno: string =""; 
        public Password: string ="";
        public imagename: string = "";
        public Status!: boolean;
        public file!: File;
}

Step 9

Add the following code in model.ts,

export class Product {
    public ProductID: number =0;
    public ProductName = '';
    public Discontinued = false;
    public UnitsInStock: number =0;
    public UnitPrice = 0;
}

Step 10

Add the following code in filtermodel.ts

export class filtermodel {
    public field=  '';
    public operator = '';
    public value  ='';
}

Step 11

Add the following code in app.planmaster.service.ts,

import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs'
import { catchError, tap } from 'rxjs/operators'
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpResponse } from '@angular/common/http';
import { GridDataResult, PageChangeEvent } from "@progress/kendo-angular-grid";
import { UserModelss } from '../models/app.UserModelss';
import { environment } from 'src/app/Shared/environment';
import {
    DataResult,
    orderBy,
    process,
    SortDescriptor
  } from "@progress/kendo-data-query";


@Injectable({
    providedIn: 'root'
})

export class PlanService 
{
    dataSource: any;
    private data: any;
    errorMessage: any;
    private apiUrl = environment.apiEndpoint + "/api/User/";
    token: any;
    username: any;


    constructor(private http: HttpClient) {
        this.data = JSON.parse(localStorage.getItem('AdminUser') ||'{}');
        this.token = this.data.token;
    }


    private handleError(error: HttpErrorResponse) {
        if (error.error instanceof ErrorEvent) {
            // A client-side or network error occurred. Handle it accordingly.
            console.error('An error occurred:', error.error.message);
        } else {
            console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
        }
        return throwError('Something bad happened; please try again later.');
    };


    public getUsers(
        skip: number,
        pageSize: number,
        sortDescriptor: SortDescriptor[],
        filterTerm: number
      ): Observable<DataResult> {

debugger

      var yt=  this.GetAllUsers();
      yt.subscribe(
              allplan => {
                  
                this.dataSource=allplan;
              },
              error => this.errorMessage = <any>error
          );
        let data;
        if (filterTerm) {
          data = process(orderBy(this.dataSource, sortDescriptor), {
            filter: {
              logic: "and",
              filters: [
                {
                  field: "UserId",
                  operator: "eq",
                  value: filterTerm
                }
              ]
            }
          }).data;
        } else {
            
          data = orderBy(this.dataSource, sortDescriptor);
        }
        return of({
          data: data.slice(skip, skip + pageSize),
          total: data.length
        });
      }

    public GetAllUsers() {
        debugger
        
        var apiUrl = environment.apiEndpoint + "/api/User/";
         let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
         headers = headers.append('Authorization', 'Bearer ' + `${this.token}`);
         return this.http.get<UserModelss[]>(this.apiUrl, { headers: headers }).pipe(tap(data => data),
             catchError(this.handleError)
         );
     }
}

Step 12

Add the following code in edit.service.ts,

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject, of, throwError  } from 'rxjs';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';
import { environment } from 'src/app/Shared/environment';
import { catchError, tap,map } from 'rxjs/operators';
import { UserModel } from '../models/app.UserModel';
import { filtermodel } from '../models/filtermodel';
import { NotificationService } from "@progress/kendo-angular-notification";
import { Component, ViewChild, TemplateRef, Input, Output, EventEmitter } from "@angular/core";

const CREATE_ACTION = 'create';
const UPDATE_ACTION = 'update';
const REMOVE_ACTION = 'destroy';

@Injectable()
export class EditService extends BehaviorSubject<any[]> {
    @ViewChild("template", { read: TemplateRef })
    public notificationTemplate: TemplateRef<any> | undefined;
    token: any;
    public apiUrl = environment.apiEndpoint + "/api/User/";
    private data: any;
    constructor(private http: HttpClient,private notificationService: NotificationService) {
        super([]);
        this.data = JSON.parse(localStorage.getItem('AdminUser') ||'{}');
        this.token = this.data.token;
    }
    public read() {
        if (this.data.length) {
            return super.next(this.data);
        }
        this.GetAllUsers()
            .pipe(
                tap(data => {
                    this.data = data;
                })
            )
            .subscribe(data => {
                super.next(data);
            });
    }
    public GetUserId(Id :any) {
        this.apiUrl = environment.apiEndpoint + "/api/User/";
        var editUrl = this.apiUrl + Id;
        let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
        headers = headers.append('Authorization', 'Bearer ' + `${this.token}`);
        return this.http.get<UserModel>(editUrl, { headers: headers }).pipe(tap(data => data),
            catchError(this.handleError)
        );
    }
    public GetUserName(UserName :any) {
        this.apiUrl = environment.apiEndpoint + "/api/User/";
        var editUrl = this.apiUrl+"GetByUserName?username=" + UserName;
        let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
        headers = headers.append('Authorization', 'Bearer ' + `${this.token}`);
        return this.http.get<UserModel>(editUrl, { headers: headers }).pipe(tap(data => data),
            catchError(this.handleError)
        );
    }
        // Save User
public SaveUser(usermodel: UserModel) 
{
let formdata = new FormData();
const file = usermodel.file;     
formdata.append("UserName",usermodel.UserName);
formdata.append("Contactno",usermodel.Contactno);
formdata.append("EmailId",usermodel.EmailId);
formdata.append("FullName",usermodel.FullName);
formdata.append("Password",usermodel.Password);
formdata.append("imagename",usermodel.imagename);
formdata.append("Status","true");
formdata.append('file', usermodel.file);
  this.apiUrl = environment.apiEndpoint + "/api/User";
  var putUrl = this.apiUrl+"/" + usermodel.UserId;
  let headers = new HttpHeaders({ 'Authorization': 'Bearer ' + `${this.token}` });
if(usermodel.UserId>0)
{
    //headers = headers.append('Authorization', 'Bearer ' + `${this.token}`);
    return this.http.put<any>(putUrl, formdata, { headers: headers })
        .pipe(
            catchError(this.handleError)
        );
}
else
{
    return this.http.post<any>(this.apiUrl, formdata, { headers: headers })
    .pipe(
        catchError(this.handleError)
    );
  }
}
    public save(data: any, isNew?: boolean) {
        const action = isNew ? CREATE_ACTION : UPDATE_ACTION;
        this.reset();
        this.GetAllUsers()
            .subscribe(() => this.read(), () => this.read());
    }
    public remove(data: any) {
        this.reset();
        var deleteUrl = this.apiUrl + data.UserId;
        let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
        headers = headers.append('Authorization', 'Bearer ' + `${this.token}`);
            return this.http.delete<any>(deleteUrl, { headers: headers })
            .pipe(
                catchError(this.handleError)
            );
    }
    public resetItem(dataItem: any) {
        if (!dataItem) { return; }
        // find orignal data item
        const originalDataItem = this.data.find((item: { ProductID: any; }) => item.ProductID === dataItem.ProductID);
        // revert changes
        Object.assign(originalDataItem, dataItem);
        super.next(this.data);
    }
    private reset() {
        this.data = [];
    }
    public GetAllUsers() {
        
        var apiUrl = environment.apiEndpoint + "/api/User/";
         let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
         headers = headers.append('Authorization', 'Bearer ' + `${this.token}`);
         return this.http.get<UserModel[]>(this.apiUrl, { headers: headers }).pipe(tap(data => data),
             catchError(this.handleError)
         );
     }

     public GetAllserverUsers(pageSize: number,skip: number,model: filtermodel) {        
        let formdata = new FormData();             
        formdata.append("field","");
        formdata.append("operatortype","");
        formdata.append("value","");
        formdata.append("pageSize",""+pageSize +"");
        formdata.append("skip", ""+ skip +"");
        var putUrl = this.apiUrl+"GetAllServerList";
        let headers = new HttpHeaders({ 'Authorization': 'Bearer ' + `${this.token}` });

         return this.http.post<any>(putUrl, formdata, { headers: headers })
         .pipe(tap(data => data),
             catchError(this.handleError)
         );
     }
     public GetFilteredUsers(pageSize: number,skip: number,model: string) {
        debugger
        let formdata = new FormData();
              
         formdata.append("model",model);
       
        var putUrl = this.apiUrl+"GetFilteredList";
       
        let headers = new HttpHeaders({ 'Authorization': 'Bearer ' + `${this.token}` });

         return this.http.post<any>(putUrl, formdata, { headers: headers })
         .pipe(tap(data => data),
         catchError(this.handleError)

         );
     }
    private fetch(action: string = '', data?: any): Observable<any[]> {
        return this.http
            .jsonp(`https://demos.telerik.com/kendo-ui/service/Products/${action}?${this.serializeModels(data)}`, 'callback')
            .pipe(map(res => <any[]>res));
    }

    private serializeModels(data?: any): string {
        return data ? `&models=${JSON.stringify([data])}` : '';
    }
    private handleError(error: HttpErrorResponse) {
        if (error.error instanceof ErrorEvent) {
            console.error('An error occurred:', error.error.message);
        } else {
         
            console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
        }
      
        return throwError('Something bad happened; please try again later.');
    };
    public showSuccess(): void {
        this.notificationService.show({
          content: "User saved successfully",
          hideAfter: 600,
          position: { horizontal: "center", vertical: "top" },
          animation: { type: "fade", duration: 400 },
          type: { style: "success", icon: true },
        });
      }
      public showError(result:string): void {

        let contentmessage="";
        contentmessage= result;
        this.notificationService.show({
          content: contentmessage,
          hideAfter: 600,
          position: { horizontal: "center", vertical: "top" },
          animation: { type: "fade", duration: 400 },
          type: { style: "error", icon: true },
        });
      }
}

Step 13

Add the following code in edit-form.component.ts,

import { Validators, FormGroup, FormControl,FormBuilder } from '@angular/forms';
import { Product } from './models/model';
import { EditService } from './service/edit.service';
import { Component, ViewChild, TemplateRef, Input, Output, EventEmitter } from "@angular/core";
import { UserModel } from './models/app.UserModel';
import { NotificationService } from "@progress/kendo-angular-notification";
import { SelectEvent,RemoveEvent,FileRestrictions,
  } from "@progress/kendo-angular-upload";
@Component({
  selector: 'kendo-grid-edit-form',
  templateUrl: './editform.component.html',
    styles: [
        `
            input[type='text'] {
                width: 100%;
            }
            .k-inline-checkbox {    
                display: inline-flex;
            }
            .img-preview {
                position: relative;
                padding: 10px;
                top: 20px;
                width: 100px;
              }
        
              event-log {
                position: relative;
                top: 20px;
              }
    ],
})
export class GridEditFormComponent {
    public active = false;
  private _editService;
  usermodel: UserModel = new UserModel();
  output: any;
  uploadSaveUrl = 'saveUrl'; // should represent an actual API endpoint
    uploadRemoveUrl = 'removeUrl'; // should represent an actual API endpoint
    @ViewChild("template", { read: TemplateRef })
    public notificationTemplate: TemplateRef<any> | undefined;
    public data: any = {
        avtar: []
    };
    public myFiles: Array<any> | undefined;
defaultimg :string ="/assets/img/0.jpg";
    
    public submitted = false;
    public restrictions: FileRestrictions = {
        allowedExtensions: ['jpg', 'jpeg', 'png']
    };

    public ngOnInit(): void {
        this.editForm = new FormGroup({
            files: new FormControl(this.myFiles),
            UserId: new FormControl(),
        FullName: new FormControl('', Validators.required),
        UserName: new FormControl('', Validators.required),
        EmailId: new FormControl('', Validators.required),
        Password: new FormControl('', Validators.required),
        imagename: new FormControl(''),
        Contactno: new FormControl(0)
        });
    }
    public editForm: FormGroup = new FormGroup({
        UserId: new FormControl(),
        FullName: new FormControl('', Validators.required),
        UserName: new FormControl('', Validators.required),
        EmailId: new FormControl('', Validators.required),
        Password: new FormControl('', Validators.required),
        Contactno: new FormControl(0),
        imagename: new FormControl(''),
        files: new FormControl(this.data.avtar)
    });
    constructor(private editServices: EditService,private fb: FormBuilder,private notificationService: NotificationService) {
        this._editService = editServices;
        this.editForm = this.fb.group({
            files: [this.myFiles, [Validators.required]]
        });
    }
    @Input() public isNew = false;

    @Input() public set model(product: any) {
        this.editForm.reset(product);
        this.active = product !== undefined;

     if(this.active)
     {
        this.defaultimg=product.imagename??null;
     }
      

    }

    @Output() cancel: EventEmitter<any> = new EventEmitter();
    @Output() save: EventEmitter<Product> = new EventEmitter();
    public onSave(e :any): void {        
        e.preventDefault();
        this.active = false;
this.usermodel.UserId=this.editForm.value.UserId;
this.usermodel.UserName=this.editForm.value.UserName;
this.usermodel.Contactno=this.editForm.value.Contactno;
this.usermodel.EmailId=this.editForm.value.EmailId;
this.usermodel.FullName=this.editForm.value.FullName;
this.usermodel.Password=this.editForm.value.Password;
this.usermodel.imagename=this.editForm.value.imagename;
this.usermodel.file=this.editForm.value.files!= null?this.editForm.value.files[0]:null;
        this._editService.SaveUser(this.usermodel).subscribe(
            response => {
              debugger
            this.output = response
            if (this.output.StatusCode == "409") {
              //  alert('User Already Exists');
                this.showError();
            }
            else if (this.output.StatusCode == "200") {
              //  alert('User Created Successfully');
                this.showSuccess()
                this.save.emit();
            }
            else {
                alert('Something Went Wrong');
            }
        });
    }
    public onCancel(e : any): void {
        e.preventDefault();
        this.closeForm();
    }
    public closeForm(): void {
        this.active = false;
        this.cancel.emit();
    }  
      public events: string[] = [];
      public imagePreviews: any[] = [];  
      public removeEventHandler(e: RemoveEvent): void {
        debugger
        this.log(`Removing ${e.files[0].name}`);    
        const index = this.imagePreviews.findIndex(
          (item) => item.uid === e.files[0].uid
        );
    
        if (index >= 0) {
          this.imagePreviews.splice(index, 1);
        }
      }    
      public selectEventHandler(e: SelectEvent): void {
        const that = this;    
        e.files.forEach((file) => {
          that.log(`File selected: ${file.name}`);
    
          if (!file.validationErrors) {
            const reader = new FileReader();
    
            reader.onload = function (ev) {
              const image = {
                src: ev.target!["result"],
                uid: file.uid,
              };
    
              that.imagePreviews.unshift(image);
            };
    
            reader.readAsDataURL(file.rawFile!);
          }
        });
      }   
      private log(event: string): void {
        this.events.unshift(`${event}`);
      }
  public showSuccess(): void {
        this.notificationService.show({
          content: "User saved successfully",
          hideAfter: 600,
          position: { horizontal: "center", vertical: "top" },
          animation: { type: "fade", duration: 400 },
          type: { style: "success", icon: true },
        });
      }
      public showError(): void {
        this.notificationService.show({
          content: "User Already Exists",
          hideAfter: 600,
          position: { horizontal: "center", vertical: "top" },
          animation: { type: "fade", duration: 400 },
          type: { style: "error", icon: true },
        });
    }
}

Step 14

Add the following code in editform.component.html,

<kendo-dialog *ngIf="active" [width]="300" [height]="450" (close)="closeForm()">
    <kendo-dialog-titlebar>
        {{ isNew ? 'Add new product' : 'Edit product' }}
    </kendo-dialog-titlebar>
    <form novalidate class="k-form" [formGroup]="editForm">
        <div *ngIf="imagePreviews.length" class="avatar">
            <kendo-avatar 
              *ngFor="let image of imagePreviews"
              [imageSrc]="image.src"
              alt="image preview"
              width="128px"
              height="128px"
              [border]="true"
              shape="circle"
              ></kendo-avatar>
          </div>
        <div class="avatar" *ngIf="!imagePreviews.length">
          <kendo-avatar 
            [border]="true"
            shape="circle"
            [imageSrc]="defaultimg"
            width="128px"
            height="128px"
          ></kendo-avatar>         
        </div>
        <kendo-fileselect formControlName="files"
        [multiple]="false" 
      [restrictions]="restrictions"
      (select)="selectEventHandler($event)"
      (remove)="removeEventHandler($event)"
    >
    </kendo-fileselect > 
        <kendo-formfield>
            <kendo-label [for]="FullName" text="Full Name"></kendo-label>
            <input formControlName="FullName" kendoTextBox #FullName required />
            <kendo-formhint>Type product name</kendo-formhint>
            <kendo-formerror>Error: Product name is required</kendo-formerror>
        </kendo-formfield>
        <kendo-formfield>
            <kendo-label [for]="UserName" text="User Name"></kendo-label>
            <input formControlName="UserName" kendoTextBox #UserName required />
            <kendo-formhint>Type User name</kendo-formhint>
            <kendo-formerror>Error: User name is required</kendo-formerror>
        </kendo-formfield>
        <kendo-formfield>
            <kendo-label [for]="EmailId" text="Email"></kendo-label>
            <input formControlName="EmailId" kendoTextBox #EmailId required />
            <kendo-formhint>Type Email Id</kendo-formhint>
            <kendo-formerror>Error: Email is required</kendo-formerror>
        </kendo-formfield>
        <kendo-formfield>
            <kendo-label [for]="Contactno" text="Contact No."></kendo-label>
            <input formControlName="Contactno" kendoTextBox #Contactno required />

            <kendo-formhint>Type Contact No.</kendo-formhint>
            <kendo-formerror>Error: Contact No. is required</kendo-formerror>
        </kendo-formfield>
        <kendo-formfield>
            <kendo-label [for]="Password" text="Password"></kendo-label>
            <input formControlName="Password" kendoTextBox #Password required type="password" />

            <kendo-formhint>Type Password.</kendo-formhint>
            <kendo-formerror>Error: Password is required</kendo-formerror>
        </kendo-formfield>
        <kendo-formfield>
            <input  formControlName="imagename" kendoTextBox #imagename  type="hidden" />
        </kendo-formfield>
    </form>
    <kendo-dialog-actions>
        <button class="k-button" (click)="onCancel($event)">Cancel</button>
        <button class="k-button k-primary" [disabled]="!editForm.valid" (click)="onSave($event)">Save</button>
    </kendo-dialog-actions>
</kendo-dialog>

Step 15

Add the following code in userlist.component.css,

.k-grid-div-root{
    position: fixed;
    left: 20%;
}

Step 16

Add the following code in userlist.component.html,

<div class="k-grid-div-root"><kendo-grid  [kendoGridBinding]="gridData"  [pageSize]="10"
  [pageable]="true"
  [height]="510"
  (dataStateChange)="onStateChange($event)"
  (edit)="editHandler($event)" (remove)="removeHandler($event)"
  (add)="addHandler()"
  [columnMenu]="true"
  [filterable]="true"
  [sortable]="true">
  >
  <ng-template kendoGridToolbarTemplate>
    <button kendoGridAddCommand>Add new</button>
</ng-template>
  <kendo-grid-column field="FullName" [width]="140"></kendo-grid-column>
  <kendo-grid-column field="UserName" [width]="120"></kendo-grid-column>
  <kendo-grid-column field="EmailId" [width]="100"></kendo-grid-column>
  <kendo-grid-column field="Contactno" [width]="130"></kendo-grid-column>
  <kendo-grid-column
  field="imagename"
  title="imagename"
  [width]="100"
  [class]="{'text-center': true}"
  [resizable]="false"
 >
  <ng-template kendoGridCellTemplate let-dataItem > 
      <img class="flag" [src]="flagURL(dataItem)"  width="30">
  </ng-template> 
 </kendo-grid-column>
  <kendo-grid-column title="command">
    <ng-template kendoGridCellTemplate>
        <button kendoGridEditCommand [primary]="true">Edit</button>
        <button kendoGridRemoveCommand>Delete</button>
    </ng-template>
</kendo-grid-column>
</kendo-grid> 
</div>
<kendo-grid-edit-form [model]="editDataItem" [isNew]="isNew"
(save)="saveHandler($event)"
(cancel)="cancelHandler()">
</kendo-grid-edit-form>

Step 17

Add the following code in userlist.component.ts,

import { Component, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { PlanService } from './service/app.planmaster.service';
import { EditService } from './service/edit.service';
import { State, process } from '@progress/kendo-data-query';
import { Product } from './models/model';

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

  private _planService;
  private _editService;

  defaultimg :string ="/assets/img/0.jpg";

  public gridData: any[] =[];
  errorMessage: any;
  public editDataItem: any;
  public isNew!: boolean;

  public gridState: State = {
    sort: [],
    skip: 0,
    take: 10
};
  constructor(private planService: PlanService, private editServices: EditService,private sanitizer:DomSanitizer) {
        this._planService = planService;
        this._editService = editServices;
   }
  ngOnInit(): void {
    debugger
    this.GetUsers()
  }
  GetUsers(){
    debugger
    this._planService.GetAllUsers().subscribe(
        alluser => {
          debugger
            this.gridData = alluser
        //    this.flagURL(this.gridData)
        },
        error => this.errorMessage = <any>error
    );
}
public flagURL(dataItem: any) { 
  debugger
  let imageurl = this.defaultimg;
  if(dataItem.imagename!=null && dataItem.imagename!="null")
  {
   imageurl =   dataItem.imagename;
  }
  return  this.sanitizer.bypassSecurityTrustUrl(imageurl);
}
public onStateChange(state: State) {
  debugger
  this.gridState = state;
  this.editServices.read();
}
public addHandler() {  
  this.editDataItem = new Product();
  this.isNew = true;
}
public editHandler({  dataItem } :any) {  
  this.editDataItem = dataItem;
  this.isNew = false;
}
public cancelHandler() {
  this.GetUsers();
}
public saveHandler(product: Product) {
  this.GetUsers();
}
public removeHandler({dataItem} :any) { 
  if (confirm("Are you sure to delete User ?")) {
      this.editServices.remove(dataItem).subscribe
          (
          response => {
              if (response.StatusCode == "200") {
                  alert('Deleted User Successfully');
                  this.GetUsers();
              }
              else {
                  alert('Something Went Wrong');
                 // this._Route.navigate(['/AllSchemeMaster']);
              }
          }
        )
      } 
   }
}

Step 18

Add the following code 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';
import { LoginComponent } from './login/login.component';
import { LogoutComponent } from './logout/logout.component';
import { UserlistComponent } from './userlist/userlist.component';
const routes: Routes = [
  {
    path: 'Admin',
    component: LayoutComponent,
    children: [
      { path: 'UserList', component : UserlistComponent }
    ]
  },
  {
    path: '',
    component: LayoutComponent,
    children: [
      { path: '', component : UserlistComponent }
    ]
  },
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Step 19

Add the following code in app.component.html,

<router-outlet></router-outlet>

Step 20

Add the following code in app.component.ts,

import { Component } from '@angular/core';
import { GridDataResult, PageChangeEvent } from "@progress/kendo-angular-grid";
import { SortDescriptor } from "@progress/kendo-data-query";
import { Observable } from "rxjs";
import { ProductService } from "../product.service";
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ProductService]
})
export class AppComponent {
  public gridItems: Observable<GridDataResult> = new Observable<GridDataResult>();
  public pageSize: number = 10;
  public skip: number = 0;
  public sortDescriptor: SortDescriptor[] = [];
  public filterTerm: number = 0;
  constructor(private service: ProductService) {
    this.loadGridItems();
  }
  public pageChange(event: PageChangeEvent): void {
    this.skip = event.skip;
    this.loadGridItems();
  }
  private loadGridItems(): void {
    this.gridItems = this.service.getProducts(
      this.skip,
      this.pageSize,
      this.sortDescriptor,
      this.filterTerm
    );
  }
  public handleSortChange(descriptor: SortDescriptor[]): void {
    this.sortDescriptor = descriptor;
    this.loadGridItems();
  }
}

Step 21

Add the following code in app.module.ts,

import { NgModule } from '@angular/core';
import 'hammerjs';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { HttpClientModule, HttpClientJsonpModule } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LayoutComponent } from './layout/layout.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { LoginComponent } from './login/login.component';
import { LogoutComponent } from './logout/logout.component';
import { UserlistComponent } from './userlist/userlist.component';
import { GridEditFormComponent } from './userlist/edit-form.component';
import { EditService } from './userlist/service/edit.service';
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';
import { SharedModule } from '@progress/kendo-angular-grid';
import { GridModule } from '@progress/kendo-angular-grid';

@NgModule({
  declarations: [
    AppComponent,
    LayoutComponent,
    DashboardComponent,
    UserlistComponent,
    LogoutComponent,
    LoginComponent,
    GridEditFormComponent
  ],
  imports: [
      BrowserModule,
      AppRoutingModule,
      GridModule,
      BrowserAnimationsModule,
      InputsModule,
      LabelModule,
      ChartsModule,
      ButtonsModule,
      DialogModule,
      UploadModule,
      FileSelectModule,
      PDFExportModule,
      NotificationModule,
      NavigationModule,
      IconsModule,
      IndicatorsModule,
      LayoutModule,
      FormsModule,
      ReactiveFormsModule,
      RouterModule,
      HttpClientModule,
      HttpClientJsonpModule,
      CommonModule,
      FormsModule,
      GridModule,
      SharedModule
  ],
  providers: [
{
    deps: [HttpClient],
    provide: EditService
}
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now run the following command

npm i
ng serve open

Summary

In this article, we learned how to create angular project, set routing, and perform CURD operations with API.