In this article, we are going to learn about how we can setup Angular 6.0 in ASP.Net Core Web API project and develop the contact list & form component using Angular Material UI.
To setup Angular 6.0 in the project, first, we have to install NodeJS in the development environment. We can download NodeJS installer from NodeJS website. and then check the version on NodeJS as below.
Now, let us globally install Angular CLI package by enter “npm install –g angular/[email protected]”, as shown in below screenshot.
Scaffold Angular
To scaffold Angular, enter “ng new Contact-App --skip-install” command in VS code terminal as below.
Here, --skip-install option is used to skip installation of the npm packages. And Contact-App is our Angular app name.
After the project is created, we move all the files & folders from Contact-App to Root folder as below:
Then we enter ‘npm install’ command in terminal to install all required packages for Angular.
Change Angular Configuration
Go to ‘angular.json’ file, it is a configuration schema file.
We changed ‘wwwroot’ folder path in OutputPath.
Then enter ng build command in terminal.
We can see generated files under wwwroot folder.
Configure startup to route to angular application
We have added the following code to configure method in ‘startup.cs’. Here we have setup mvc default rout to index.html that generates under wwwroot folder.
-
- app.Use(async (context, next) => {
- await next();
- if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("/api/")) {
- context.Request.Path = "/index.html";
- await next();
- }
- });
-
- app.UseDefaultFiles();
- app.UseStaticFiles();
-
- app.UseMvcWithDefaultRoute();
Now run project by enter ‘dotnet run’ command in terminal and open ‘localhost:5000’ URL in browser.
Setup angular material UI
Install angular material packages and dependencies.
Please go through this article to get more details about material components.
- ng add @angular/material
- npm install -d @angular/cdk hammerjs
To use angular material UI components in our Angular contact application, we have created a separate module named ‘app.material.module.ts’ in app folder.
In this module, we imported all dependant material components and we have included in our main app module in this module .
Then, we have imported Angular material theme in the main style.css in src folder
- @import '~@angular/material/prebuilt-themes/deeppurple-amber.css';
Then, we added this link of material icons into index.html in src folder:
- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
Generate contact list & form component
To generate new component, we used ‘ng generate component’ command as below,
This we have set up routing for that component in ‘app.routing.ts’.
- import {
- ModuleWithProviders
- } from '@angular/core';
- import {
- Routes,
- RouterModule
- } from '@angular/router';
- import {
- AppComponent
- } from './app.component';
- import {
- ContactlistComponent
- } from './contactlist/contactlist.component';
- import {
- ContactformComponent
- } from './contactform/contactform.component';
- const appRoutes: Routes = [{
- path: '',
- pathMatch: 'full',
- component: ContactlistComponent
- }, {
- path: 'contactform',
- component: ContactformComponent
- }];
- export const Routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
Create angular services
To create a consumed contact API that we have created Part 1; we are generating Angular contact services class in app folder using this command:
‘ng generate service contact’
- import {
- Injectable
- } from '@angular/core';
- import {
- HttpClient,
- HttpParams,
- HttpErrorResponse
- } from '@angular/common/http';
- import {
- HttpHeaders
- } from '@angular/common/http';
- import {
- Observable,
- throwError
- } from 'rxjs';
- import {
- catchError
- } from 'rxjs/operators';
- import {
- IContact
- } from '../model/contact';
- const httpOptions = {
- headers: new HttpHeaders({
- 'Content-Type': 'application/json'
- })
- };
- @Injectable()
- export class ContactService {
- constructor(private http: HttpClient) {}
-
- getAllContact(url: string): Observable < IContact[] > {
- return this.http.get < IContact[] > (url).pipe(catchError(this.handleError));
- }
-
- addContact(url: string, contact: IContact): Observable < any > {
- return this.http.post(url, JSON.stringify(contact), httpOptions).pipe(catchError(this.handleError));
- }
-
- updateContact(url: string, id: number, contact: IContact): Observable < any > {
- const newurl = `${url}?id=${id}`;
- return this.http.put(newurl, contact, httpOptions).pipe(catchError(this.handleError));
- }
-
- deleteContact(url: string, id: number): Observable < any > {
- const newurl = `${url}?id=${id}`;
- return this.http.delete(newurl, httpOptions).pipe(catchError(this.handleError));
- }
-
- 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.');
- }
- }
Update main app html template
We have included router outlet place holder to render component based on Angular route.
- <!--The content below is only a placeholder and can be replaced.-->
- <mat-toolbar> <span>Contact Application</span> </mat-toolbar>
- <router-outlet></router-outlet>
Update contact form component
In contact form component, we used form group named as 'contactFrm' to bind model with each control and injected dialog data to bind form based on request parameter.
contactform.component.html
- <form (ngSubmit)="onSubmit(contactFrm)" [formGroup]="contactFrm">
- <h2>{{data.modalTitle}}</h2>
-
- <div>
- <mat-form-field appearance="outline">
- <mat-label>Name</mat-label>
- <input matInput placeholder="Name" formControlName="name">
-
-
- <mat-error *ngIf="formErrors.name">
- {{ formErrors.name }}
- </mat-error>
- </mat-form-field>
- </div>
- <div>
- <mat-form-field appearance="outline">
- <mat-label>Email</mat-label>
- <input type="email" matInput placeholder="email" formControlName="email">
- <mat-error *ngIf="formErrors.email">
- {{ formErrors.email }}
- </mat-error>
- </mat-form-field>
-
- </div>
- <p>
- <mat-radio-group class="contact-radio-group" formControlName="gender" >
- <mat-radio-button class="contact-radio-button" *ngFor="let gndr of genders" [value]="gndr.id">
- {{ gndr.name }}
- </mat-radio-button>
- </mat-radio-group>
- <mat-error *ngIf="formErrors.gender">
- {{ formErrors.gender }}
- </mat-error>
- </p>
- <div>
- <mat-form-field appearance="outline">
- <input matInput [matDatepicker]="picker" placeholder="Choose a birthday" formControlName="birth">
- <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
- <mat-datepicker #picker></mat-datepicker>
-
- <mat-error *ngIf="formErrors.birth ">
- {{ formErrors.birth }}
- </mat-error>
- </mat-form-field>
- </div>
- <div>
- <mat-form-field appearance="outline">
- <mat-select placeholder="Select a Technology" formControlName="techno">
- <mat-option>-- None --</mat-option>
- <mat-option *ngFor="let techno of technologies" [value]="techno">
- {{ techno }}
- </mat-option>
- </mat-select>
- <mat-error *ngIf="formErrors.techno ">
- {{ formErrors.techno }}
- </mat-error>
- </mat-form-field>
- </div>
- <div>
- <mat-form-field appearance="outline">
- <textarea matInput placeholder="Message..." formControlName="message"></textarea>
- <mat-error *ngIf="formErrors.message ">
- {{ formErrors.message }}
- </mat-error>
- </mat-form-field>
- </div>
- <div>
-
- <button type="button" mat-raised-button color="warn" (click)="dialogRef.close()">Cancel</button>
- <button type="submit" mat-raised-button color="primary" [disabled]="contactFrm.invalid">{{data.modalBtnTitle}}</button>
- </div>
-
- </form>
To see contactform.component.ts code please refer this
GitHub link and final form looks as shown in the below screenshot,
Update contact list component
In contact list component, we have used material table to bind contact record using ‘MatTableDataSource’ and called contact service to retrieve data from API. Then we used MatDialog to open contact form component.
contactlist.component.html
- <div class="spinner" *ngIf="loadingState; else contactlist">
- <mat-spinner></mat-spinner>
- </div>
- <ng-template class="contactlist" #contactlist>
- <h2 style="text-align: center;">Contact List</h2>
- <div class="contactlist-container mat-elevation-z8">
- <div><button title="Create" mat-raised-button color="accent" (click)="addContact()">Create</button></div>
- <table mat-table #table [dataSource]="dataSource">
-
-
- <!-- <ng-container matColumnDef="id">
- <th mat-header-cell *matHeaderCellDef> Id </th>
- <td mat-cell *matCellDef="let element"> {{element.id}} </td>
- </ng-container> -->
-
-
- <ng-container matColumnDef="name">
- <th mat-header-cell *matHeaderCellDef> Name </th>
- <td mat-cell *matCellDef="let element"> {{element.name}} </td>
- </ng-container>
-
-
- <ng-container matColumnDef="email">
- <th mat-header-cell *matHeaderCellDef> Email </th>
- <td mat-cell *matCellDef="let element"> {{element.email}} </td>
- </ng-container>
-
-
- <ng-container matColumnDef="gender">
- <th mat-header-cell *matHeaderCellDef> Gender </th>
- <td mat-cell *matCellDef="let element"> {{getGender(element.gender)}} </td>
- </ng-container>
-
-
- <ng-container matColumnDef="birth">
- <th mat-header-cell *matHeaderCellDef> Birthday </th>
- <td mat-cell *matCellDef="let element"> {{element.birth | date: 'MM-dd-yyyy' }} </td>
- </ng-container>
-
-
- <ng-container matColumnDef="techno">
- <th mat-header-cell *matHeaderCellDef> Technology </th>
- <td mat-cell *matCellDef="let element"> {{element.techno}} </td>
- </ng-container>
-
-
- <ng-container matColumnDef="message">
- <th mat-header-cell *matHeaderCellDef> Message </th>
- <td mat-cell *matCellDef="let element"> {{element.message}} </td>
- </ng-container>
-
- <ng-container matColumnDef="action">
- <th mat-header-cell *matHeaderCellDef> Action </th>
- <td mat-cell *matCellDef="let element">
- <button title="Edit" mat-raised-button color="primary" (click)="editContact(element.id)">Edit</button>
- <button title="Delete" mat-raised-button color="warn" (click)="deleteContact(element.id)">Delete</button>
- </td>
- </ng-container>
-
- <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
- <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
- </table>
-
- </div>
- </ng-template>
To see contactlist.component.ts code please refer to this
GitHub link.
Build components and run the project
Our component is ready. Now build Angular project using 'ng build' command and then run the project by entering 'dotnet run' command in terminal.
Conclusion
This is how we created contact application using ASP.Net Core Web API, Angular 6.0, and Visual Studio code.
You can see the entire code on
GitHub and fork it for the starter project.
Please let me know your feedback.