Angular 9-Simple Example with ASP.NET Core 3.1 Web API

In this article, I'm going to show you how to create a front end client side app using Angular


Execute the following command using the command prompt


> ng new OrderUI
> cd OrderUI
> code .

angular_9_1.png

The "code ." is used to open the project in Visual Studio Code.


angular_9_2.png

> ng serve --o

After the above command is executed, you will be looked like the following screenshot on your browser.


angular_9_3.png

angular_9_4.png

For this project, I want to create a page with an order form and order list. So, for this page, I will create a parent component with two child components.


To create these components, execute the following commands. (Note : To terminate batch job, press the CTRL+C keys)


ng g c orders -s --skipTests

The above code is used to create the parent component. Its name is orders.


Type the following commands for two child components


ng g c orders/order -s --skipTests
ng g c orders/order-list -s --skipTests

angular_9_5.png

Replace the app.component.html as shown below.


<div class="container">
	<app-orders></app-orders>
</div>

Execute the following code to see the work of the orders component in your browser.


angular_9_6.png

Replace the orders.component.html as follows


<div class="jumbtron">
	<h1 class="display-4 text-center">Orders</h1>
	<hr>
	<div class="row">
		<div class="col-md-5">
			<app-order></app-order>
		</div>
		<div class="col-md-7">
			<app-order-list></app-order-list>
		</div>
	</div>
</div>

angular_9_7.png

I will be using Bootstrap and Font Awesome Icons for the appearance of the app. Now install them using the following command.


> npm install bootstrap --save
> npm install font-awesome --save

Add the following line inside src > style.css file.

@import "~bootstrap/dist/css/bootstrap.min.css"
@import "~font-awesome/css/font-awesome.css";

Now, you can use the Bootstrap classes. Run the app and you will see the following appearance.


angular_9_8.png

Replace the order.component.html as follows.


<form>
    <div class="form-group">
        <div class="input-group">
            <div class="input-group-prepend">
                <div class="input-group-text bg-white">
                    <i class="fa fa-shopping-cart"></i>
                </div>
            </div>
            <input name="Name" class="form-control" placeholder="Enter Order Name" required>
        </div>
    </div>
    <div class="form-row">
        <div class="form-group col-md-9">
            <div class="input-group">
                <div class="input-group-prepend">
                    <div class="input-group-text bg-white">
                        <i>Received Date</i>
                    </div>
                </div>
                <input name="ReceivedDate" class="form-control" placeholder="MM/DD/YYYY" required maxlength="10" minlength="10">
            </div>
        </div>
        <div class="form-group col-md-3">
            <div class="input-group">
                <input name="Quantity" class="form-control" placeholder="Quantity" required maxlength="3" minlength="1" type="number" style="text-align: right;">
            </div>
        </div>
    </div>
    <div class="form-group">
        <button class="btn btn-success btn-lg btn-block" type="submit">Add</button>
    </div>
</form>

angular_9_9.png

Replace the order-list.component.html as follows


<table class="table">
    <tr>
        <td>1L Water</td>
        <td>04/21/2020</td>
        <td>1</td>
    </tr>
    <tr>
        <td>1L Milk</td>
        <td>04/22/2020</td>
        <td>2</td>
    </tr>
    <tr>
        <td>2L Water</td>
        <td>05/01/2020</td>
        <td>3</td>
    </tr>
</table>

angular_9_10.png

Let's consume an ASP.NET Core Web API from Angular


Download the Web API from https://github.com/cihanasn/Order


Open the Web API using Visual Studio 2019 Community


Start the project


angular_9_11.png

Create a model class in the client side app. First create a folder named shared


angular_9_12.png

Execute the following command to create the model "Order" that is similar to the Order class file(Models/Order.cs) in the Order API


ng g class shared/order --type=model --skipTests

angular_9_13.png

Replace the Order model as follows


export class Order {
    ID: number;
    Name: string;
    Quantity: number;
    ReceivedDate: string;
}

Create a service class to interact with the Order API.


ng g s shared/order --skipTests

Replace the service class as follows.


import { Injectable } from '@angular/core';
import { Order } from './order.model';
import { HttpClient } from '@angular/common/http';
@Injectable({
  providedIn: 'root'
})
export class OrderService {
  formData: Order;
  //readonly rootURL = 'http://localhost:50615/api';
  readonly rootURL = 'http://localhost:5000/api';
  list: Order[];
constructor(private http: HttpClient) { }
postOrder()
  {
    return this.http.post(this.rootURL + '/Order', this.formData);
  }
getList()
  {
    this.http.get(this.rootURL + '/Order')
    .toPromise()
    .then(res => this.list = res as Order[]);
  }
  
  putOrder() {
    return this.http.put(this.rootURL + '/Order/'+ this.formData.ID, this.formData);
  }
deleteOrder(ID) {
    return this.http.delete(this.rootURL + '/Order/'+ ID);
  }
}

The formData property is used to obtain the form values.


HttpClient is used to send a request to the API. Before sending the request, you have to start your API.
Also you must change the port of the rootURL variable with your API's port.


This service class has Injectable decorator. So that the class is used at root level.


We have to import the HttpClientModule module into the app/app.module.ts file.


Additionally we need to import the OrderService service and the FormsModule module.


import { BrowserModule } from '@angular/platform-browser';
...
import { HttpClientModule } from '@angular/common/http';
import { OrderService } from './shared/order.service';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
...
],
imports: [
...,
HttpClientModule,
FormsModule
],
providers: [OrderService],
...
})
export class AppModule { }

Let's modify order.component.ts and order.component.html to add a record to the database.


First modify the order.component.ts file as shown below.


import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { OrderService } from './../../shared/order.service';
@Component({
  selector: 'app-order',
  templateUrl: './order.component.html',
  styles: []
})
export class OrderComponent implements OnInit {
constructor(public service: OrderService) { }
ngOnInit() {
    this.resetForm();
  }
  
  resetForm(form?: NgForm) {
    if (form != null)
      form.form.reset();
    this.service.formData = {
      ID: 0,
      Name: '',
      Quantity: 0,
      ReceivedDate: ''
    }
  }
  onSubmit(form: NgForm) {
    this.insertRecord(form);
  }
insertRecord(form: NgForm) {
    this.service.postOrder().subscribe(
      res => { console.log(res); },
      err => { console.log(err); }
    )
  }
}

Then modify the order.component.html file as shown below.


<form #form="ngForm" (submit)="onSubmit(form)">
    <div class="form-group">
        <div class="input-group">
            <div class="input-group-prepend">
                <div class="input-group-text bg-white">
                    <i class="fa fa-shopping-cart"></i>
                </div>
            </div>
            <input name="Name" #Name="ngModel" [(ngModel)]="service.formData.Name" class="form-control" placeholder="Enter Order Name" required>
        </div>
    </div>
    <div class="form-row">
        <div class="form-group col-md-9">
            <div class="input-group">
                <div class="input-group-prepend">
                    <div class="input-group-text bg-white">
                        <i>Received Date</i>
                    </div>
                </div>
                <input name="ReceivedDate" #ReceivedDate="ngModel" [(ngModel)]="service.formData.ReceivedDate" class="form-control" placeholder="MM/DD/YYYY" required maxlength="10" minlength="10">
            </div>
        </div>
        <div class="form-group col-md-3">
            <div class="input-group">
                <input name="Quantity" #Quantity="ngModel" [(ngModel)]="service.formData.Quantity" class="form-control" placeholder="Quantity" required maxlength="3" minlength="1" type="number" style="text-align: right;">
            </div>
        </div>
    </div>
    <div class="form-group">
        <button class="btn btn-success btn-lg btn-block" type="submit">Add</button>
    </div>
</form>

Run the client side app with the following command.


ng serve --o

You've done only adding a record to the database. You can add an order record like the following.


angular_9_14.png

After clicking the "Add" button, You get the CORS error like this. So you have to do a few things in your API.


ASP.NET Core Web API is hosted in another domain or in another port. So by default, it will block your request.
To solve this problem, you have to enable CORS(Cross Origin Resource Sharing) in API.


By default, ASP.Net Core API use camel casing for response object. (eg: ReceivedDate to receivedDate). You have to remove default json formatting.


angular_9_15.png

Install the "Microsoft.AspNetCore.Cors" from NuGet Manager


angular_9_16.png

Open the Startup.cs file and add the following code


public void ConfigureServices(IServiceCollection services)
        {
            ...
services.AddControllers().AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.PropertyNamingPolicy = null;
                options.JsonSerializerOptions.DictionaryKeyPolicy = null;
            });
services.AddCors();
        }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseCors(options =>
            options.WithOrigins("http://localhost:4200")
            .AllowAnyMethod()
            .AllowAnyHeader());
            ...
        }

angular_9_17.png

angular_9_18.png

angular_9_19.png

As you can see above, I added the above record into my database.


To show the list of orders, Update the order-list.component.ts and order-list.component.html files


import { Component, OnInit } from '@angular/core';
import { OrderService } from './../../shared/order.service';
@Component({
  selector: 'app-order-list',
  templateUrl: './order-list.component.html',
  styles: []
})
export class OrderListComponent implements OnInit {
constructor(public service:OrderService) { }
ngOnInit(): void {
    this.service.getList();
  }
}

order-list.component.html


<table class="table">
    <tr *ngFor="let item of service.list">
        <td>{{item.Name}}</td>
        <td>{{item.ReceivedDate}}</td>
        <td>{{item.Quantity}}</td>
    </tr>
</table>

angular_9_20.png

Update the insertRecord method in the order.component.ts file to reset form and get the list of orders.


insertRecord(form: NgForm) {
    this.service.postOrder().subscribe(
      res => { 
        console.log(res);
        this.resetForm(form);
        this.service.getList();
       },
      err => { console.log(err); }
    )
  }

angular_9_21.png

angular_9_22.png

I want to add the update and delete operations into this project.


Now let's implement the update operation.


Go to the order-list.component.html and update it as follows.


<table class="table">
    <tr *ngFor="let item of service.list">
        <td (click)="populateForm(item)">{{item.Name}}</td>
        <td (click)="populateForm(item)">{{item.ReceivedDate}}</td>
        <td (click)="populateForm(item)">{{item.Quantity}}</td>
    </tr>
</table>

In the order-list.component.ts file, I will create a new method called sendForm that populate the form.


import { Component, OnInit } from '@angular/core';
import { OrderService } from './../../shared/order.service';
@Component({
  selector: 'app-order-list',
  templateUrl: './order-list.component.html',
  styles: []
})
export class OrderListComponent implements OnInit {
constructor(public service:OrderService) { }
ngOnInit(): void {
    this.service.getList();
  }
populateForm(item) {
    this.service.formData = Object.assign({}, item);
  }
}

A new method called updateRecord will be created in the order.component.ts file.
Then it will be added to the onSubmit method. But the onSubmit method contains the insertRecord method.
To choose one of these methods, I will use the ID property of the Order model. So I have done both insert and update operations inside the submit event.


Add the ID property to the order.component.html


<form #form="ngForm" (submit)="onSubmit(form)">
  <input type="hidden" name="ID" [value]="service.formData.ID">

Update the order.component.ts file as follows


onSubmit(form: NgForm) {  
    if (this.service.formData.ID == 0)
      this.insertRecord(form);
    else
      this.updateRecord(form);
  }
  updateRecord(form: NgForm) {
    this.service.putOrder().subscribe(
      res => {
        this.resetForm(form);  
        this.service.getList();
      },
      err => {
        console.log(err);
      }
    )
  }

angular_9_23.png

After clicking on the row of the table, the form is filled as shown below.


angular_9_24.png

Change the values as follows and click the Add button.


angular_9_25.png

angular_9_26.png

Update the order-list.component.html file to delete an order.


...
        <td>
            <i class="fa fa-trash text-danger" (click)="onDelete(item.ID)"></i>
        </td>
    </tr>
</table>

Then update the order-list.component.ts file


onDelete(ID) {
    if (confirm('Are you sure to delete this record?')) {
      this.service.deleteOrder(ID)
        .subscribe(res => {
          this.service.getList();
        },
        err => { console.log(err); })
    }
  }

angular_9_27.png

After deleting second row on the table, it will be appeared like the following screenshot.


angular_9_28.png

angular_9_29.png

https://github.com/cihanasn/OrderUI


Thank you for reading


See you soon, happy coding :)