To Do Rest API Using Asp.net Core – Angular Client (Part 4)

This post is a continuation for previous posts, to follow along you have to at least complete part 1 and part 2 where we built a restful web service using Asp.net Core or you can grab the source code from GitHub.
In this post we are going to create an angular client for our Web API. Angular is pretty popular out there and you can find endless tutorials but in this tutorial i’m going to keep things as simple as possible so beginners could find an easy tutorial to start with.
Related Posts
To Do Rest API Using Asp.net Core (Part 1)
To Do Rest API Using Asp.net Core – Adding Swagger (Part 2)
To Do Rest API Using Asp.net Core – Blazor Client (Part 3)
To Do Rest API Using Asp.net Core – Angular Client (Part 4) (This One)
To Do Rest API Using Asp.net Core – Flutter Client (Part 5)
Tools
- Node JS Please install the recommenced version and not the latest.
- Visual Studio Code Any code editor would work.
Getting Started
Installing angular
Open your command prompt as administrator and install angular using the following command.
npm install -g @angular/cli
The above command install the latest version of angular globally (angular 8 now). Then navigate to your work space and create a new app using the following command.
ng new ToDo-Angular
We are not going to use routing in this tutorial so choose no for routing and css for style sheets. Now that everything is ready you can build and run your app using the following command.
ng serve -o
The ng new command provided us with a starter template that we can use to build upon.
Calling The Web API From Angular
First you need to launch you Todo Rest API, to keep things simple I will put all the type script code inside app.component.ts but in production apps you should organize your code into different sections see. To be able to create http requests we need to import HttpClientModule into our app.modules .
app.modules
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, // import HttpClientModule after BrowserModule. HttpClientModule, ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Get Request
To make a get request we need to import Http Client that we referenced in app.modules. Then we inject HttpClient into our constructor, this code makes a get request to our web API and logs the response to the console.
app.component.ts
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'ToDo-Angular'; baseUrl = 'http://localhost:58635/api'; constructor(private http: HttpClient) { http.get(this.baseUrl + "/ToDos").subscribe((response) => { console.log(response); }); } }
To open the console Press Right Click and Select inspect element or use Ctrl + Shift + I. Go to the console tab, if you do not see any output refresh the page and you should see a Json array with all the Todo Items.
Displaying Todos inside our Web Page
I will try to make the closest styling possible to that we used in the blazor example, so we will need to add a reference to Bootstrap 4 and Open Iconic, to do that add the following lines to the index.html file as below, below the meta tag.
<meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/open-iconic/1.1.1/font/css/open-iconic-bootstrap.min.css" integrity="sha256-BJ/G+e+y7bQdrYkS2RBTyNfBHpA9IuGaPmf9htub5MQ=" crossorigin="anonymous" />
In order to access our API Response we need to create a variable in app.component.ts that hold our Json data. so modify your code as below.
todos: any constructor(private http: HttpClient) { http.get(this.baseUrl + "/ToDos").subscribe((response) => { this.todos = response; console.log(response); }); }
Next we need to modify our HTML template to show our DTO list. So replace the app.component.html content with the following.
<!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> </div> <div class="container"> <div class="row"> <div class="col-12"> <div class="card"> <h2>ToDos</h2> <div class="card-body"> <ul class="list-group"> <div *ngFor="let todo of todos; index as i;"> <div [ngSwitch]="todo.status"> <li *ngSwitchCase="'Pending'" class="list-group-item list-group-item-info d-flex justify-content-between align-items-center"> <span>{{todo.description}}</span> <div> <span class="font-weight-bold">{{todo.status}}</span> </div> </li> <li *ngSwitchCase="'In Progress'" class="list-group-item list-group-item-success d-flex justify-content-between align-items-center"> <span>{{todo.description}}</span> <div> <span class="font-weight-bold">{{todo.status}}</span> </div> </li> <li *ngSwitchCase="'Done'" class="list-group-item list-group-item-primary d-flex justify-content-between align-items-center"> <span>{{todo.description}}</span> <div> <span class="font-weight-bold">{{todo.status}}</span> </div> </li> <li *ngSwitchCase="'Cancelled'" class="list-group-item list-group-item-warning d-flex justify-content-between align-items-center"> <span>{{todo.description}}</span> <div> <span class="font-weight-bold">{{todo.status}}</span> </div> </li> </div> </div> </ul> </div> </div> </div> </div> </div>
Now you should see Todo list similar to what we did in the blazor project. The code is not complex, as you can see we are creating a for loop using ngFor with a nested switch statement to apply different style based on the status of the Todo item.
Adding a new Todo Item
In order to create a post request we need a form, for this we have to add an import inside our app.modules for FormsModule .
app.module.ts
. . import { HttpClientModule } from '@angular/common/http'; import { FormsModule } from '@angular/forms'; . . HttpClientModule, FormsModule
Next we will create an empty object to bind to our form. Add it below todos: any.
app.component.ts
todos: any todoModel: any = {}
Note: Usually we create TypeScript interfaces and classes instead of dummy JS objects, doing that gives us with IntelliSense, clean code and clear structure. but for this little example it would be boring to create a handful of files.
Back to our html we will create a little form and bind it to our todoModel Object. So below the div with container class add the following code.
<form #form="ngForm" (ngSubmit)="onSubmit()"> <div class="row"> <div class="col-8"> <input placeholder="Something todo" [(ngModel)]="todoModel.description" name="description" class="form-control" /> </div> <div class="col-2"> <select [(ngModel)]="todoModel.status" name="status"> <option value="Pending">Pending</option> <option value="In Progress">In Progress</option> <option value="Done">Done</option> <option value="Cancelled">Cancelled</option> </select> </div> <div class="col-2"> <button type="submit" class="btn btn-primary mb-2">Save Todo</button> </div> </div> </form>
Submit method
Below is the submit method, I have applied some refactoring to the code to make use of the get method.
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'ToDo-Angular'; baseUrl = 'http://localhost:58635/api'; todos: any todoModel: any = {} constructor(private http: HttpClient) { this.getDtos() } onSubmit() { this.http.post(this.baseUrl + "/ToDos", this.todoModel).subscribe((response) => { console.log(response); this.todoModel= {} //Empty our object this.getDtos() //Get updated dto list }); } getDtos(){ this.http.get(this.baseUrl + "/ToDos").subscribe((response) => { this.todos = response; console.log(response); }); } }
Updating a Todo Item
To update a Todo item we need to populate our form with its values and since the form is bound to the todoModel, populating this object is enough to achieve what we want. So we will add an edit button that will take the current list item and push it to the todoModel. Add the following line of code under: <span class=”font-weight-bold”>{{todo.status}}</span> inside each of the switch statements.
<span class="ml-5"><button class="btn btn-outline-primary oi oi-pencil" (click)="onEdit(todo)"></button></span>
Next we will add the edit method that take the selected Todo item as a parameter. Then inside the onSubmit method we will check if the object has an id then we make an update, else we make an add.
app.component.ts Full code
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'ToDo-Angular'; baseUrl = 'http://localhost:58635/api'; todos: any todoModel: any = {} constructor(private http: HttpClient) { this.getDtos() } onSubmit() { if(this.todoModel.id){ this.http.put(this.baseUrl + "/ToDos/" + this.todoModel.id, this.todoModel).subscribe((response) => { console.log(response); this.todoModel= {} //Empty our object this.getDtos() //Get updated dto list }); }else{ this.http.post(this.baseUrl + "/ToDos", this.todoModel).subscribe((response) => { console.log(response); this.todoModel= {} //Empty our object this.getDtos() //Get updated dto list }); } } getDtos(){ this.http.get(this.baseUrl + "/ToDos").subscribe((response) => { this.todos = response; console.log(response); }); } onEdit(todo){ this.todoModel = todo; console.log(todo); } }
Validation
In this case we want to disable the submit button in case the user did not enter a description or selected a status. so we add the required attribute to both inputs and add a check on the submit button to see of the form is valid.
<form #form="ngForm" (ngSubmit)="onSubmit()"> <div class="row"> <div class="col-8"> <input placeholder="Something todo" [(ngModel)]="todoModel.description" name="description" class="form-control" required/> </div> <div class="col-2"> <select [(ngModel)]="todoModel.status" name="status" required> <option value="Pending">Pending</option> <option value="In Progress">In Progress</option> <option value="Done">Done</option> <option value="Cancelled">Cancelled</option> </select> </div> <div class="col-2"> <button type="submit" class="btn btn-primary mb-2" [disabled]="!form.form.valid">Save Todo</button> </div> </div> </form>
Now we have a working Angular sample, In this post we discussed :
- Angular Forms
- Working with Rest API’s
- ngFor
- ngSwitch
- Form Validation
- Styling with Angular
Hope this post was helpful, you can find the source code on GitHub, Happy Coding.
i love this great article