Hello All recently Angular 7 is out and lets explore how we can create the SPA using angular and using .net core and entity framework core as a back end
Agenda
- Angular 7
- New Features
- Angular CLI Changes
- Angular Material Changes
- Upgrading to Angular 7
- Adding New Project
- Front end Design and Implementation using Angular 7
- Adding Components
- Adding Models and Config files
- Adding Bootstrap popups
- Adding Data service
- Back End Web API Development using Asp.net Core and Entity Framework Core
- Set up .NET Core project
- Setup Entity framework core
- Set up CORS to allow cross origin resource sharing.
- Future Expansion of this article
- Source code Link
Angular 7
Finally, the Wait for Angular 7 is over!! This version of the angular has got us some exciting features, primarily the changes are in Angular core , CLI and then Angular material lets explore it one by one
Angular Core Changes
Some of the Added features in the Angular Core can be listed down here
- Introduced new interface - UrlSegment [] to CanLoad interface
- New Interface DoBootStrap
- Added a new elements features - enable Shadow DOM v1 and slots
- Added a new router features - warn if navigation triggered outside Angular zone
- Added a new ability to recover from malformed URLs
- Added a new compiler support dot (.) in import statements and avoid a crash in ngc-wrapped
- Added a new "original" placeholder value on extracted XMB
- updated dependencies to support Typescript 3.1, RxJS 6.3 and Node 10.
Angular CLI Changes
Remember the Angular project setup in earlier version of the Angular u just type ng new Project Name and then CLI and in mean time CLI we can see the screen with some outputs and some data which is rendering on the screen , With Angular 7 which is the one of the cool feature and which I like the most is the Angular CLI Prompts , With this feature we have the ability to setup the project with just couple of Answers .Lets check Quickly how we can do this in following image.
Angular Material and CDK
Angular Material and CDK have come out with the new features like Virtual scrolling and Drag and Drop let’s explore them in brief
Virtual scrolling
This allows us to use the noticeable aspect of the list to load and Unload the DOM element in the page means if we have the large chunk of the data and we want to show it in the list ,then we can make use of this feature.
Drag and Drop
The Drag and Drop gets the support from CDK and includes the features like automatically rendering as the user moves items and including the helper methods for the record or transfer of items in the lists
Application performance
Everything revolves around the application and Google has invested plenty of things and introduced some feature which will help us to boost the performance first one is the Bundle Budget which lets us set the Application bundle size and gives some errors when the limit is exceeded more than that limit default size for the bundle budget will be the 2 MB which can be increased later.
Next thing is the removal of the Pollyfill.ts file which is used only during the development it is removed from the production automatically.
Upgrading to Angular 7
Well plenty of us have the project built on the old versions of the Angular , in order to upgrade the old versions of the Angular , This official web site have provided the ways and the detailed explanation of how to do that you can find it here If we are migrating from the Angular 6 to Angular 7 following command will do the work for us
ng update @angular/cli @angular/core
So far, we done with the angular features and upgrade now lets have some real action and add the project.
Adding New Project
To add angular project, we have some prerequisite to proceed further with this article,
- Installing latest Node.js which in turn will install the NPM (Node package manager) which in turn will download all the dependencies or packages for our application. The latest version of the Node.js can be found here
- Getting the Angular CLI Once we are done with the Node.js and NPM next will be to download the Angular CLI which will help us in setting up the things Quickly for installing CLI we will need following command npm install -g @angular/cli
- Getting Visual studio code This is the IDE that we will be using in this article and for installing this you can find the latest version of this right here.
Creating new project
Now its time to add new project with the Angular 7 for this let’s follow steps as below in the Figure,
- Create the Directory where you want to save the project
- Use command ng New Angular7CRUDDemo
- Choose the proper option to add the Routing and CSS
Note Depending on your machine and Internet speed it may take some time to download the package and project is ready.
Once the Project is ready lets open it from the File menu and we can see the directory structure like below,
One change we can see from the old version is the addition of the app-routing file which is added from the CLI prompt options while setting up the Project
Now Question is how we check if our project is Angular 7 compatible for that we need to check the package. json file which has structure as follows,
When we see the highlighted section we can say that the Current project is configured to use the latest version of the angular dependencies.
Now Time for Actual Coding we have divided our coding part into 2 sections first one being the UI in Angular 7 and then Web API part in the .net Core and Entity Framework Core lets first see the UI Part and then we will see the Web API part with .net core and Entity Framework core
Front end Design and Implementation using Angular
As we all know the Front end or any angular application is made up of the components so let’s see what will be the structure of the application before that lets understand what we are going to achieve in this article
Here we are going to add the Demo Application which will be used to List , Add Update and Delete the Employees for that we will have the following directory structure.
Above is the directory structure of the Application here we have 3 components namely
- Angular-crud.component.ts This will be the component which will list down all the employees and will hold other component
- employee-add.component.ts This will be the component to create the employee record
- app.component.ts The App component where all the components will be loaded through <router-outlet></router-outlet>
- Employeeupdate.component.ts This will be responsible for handling the Edit operation of the Employee record
- DataService.ts This will Hold all the API calls with various verbs using the Httpclient in the Angular 7
- Data Models This folder holds the Employee data model which will be the base for all and the config.ts file which will hold the configuration related data
- App-routing.module.ts This is the Router which will be added in the application while configuring the project.
Let’s explore these components one by one,
Code Description
employee-Add.component.ts
import { Component, OnInit,Input, ViewChild, ElementRef, EventEmitter, Output } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Employee } from 'src/Models/Employee';
import { Router } from '@angular/router';
import {EmployeeDataService} from '../DataService/EmployeeDataService'
@Component({
selector: 'app-employee-add',
templateUrl: './employee-add.component.html',
styleUrls: ['./employee-add.component.sass']
})
export class EmployeeAddComponent implements OnInit {
@Input() cleardata: boolean = false;
@Output() nameEvent = new EventEmitter<string>();
objtempemp:Employee;
@Input() objemp :Employee=new Employee();;
@ViewChild('closeBtn') cb: ElementRef;
constructor(private dataservice:EmployeeDataService,private route:Router) {
}
ngOnInit() {
}
ResetValues(){
}
Register(regForm:NgForm){
this.objtempemp=new Employee();
this.objtempemp.email=regForm.value.email;
this.objtempemp.firstname=regForm.value.firstname;
this.objtempemp.lastname=regForm.value.lastname;
this.objtempemp.gender=regForm.value.gender;
this.dataservice.AddEmployee(this.objtempemp).subscribe(res=>{
alert("Employee Added successfully");
this.TakeHome();
}
)
}
TakeHome(){
this.nameEvent.emit("ccc");
this.cb.nativeElement.click();
this.route.navigateByUrl('');
}
}
Employee-add.component.html
<div class="container" style="border:thin">
<form #empadd='ngForm' (ngSubmit)="Register(empadd)" class="form-horizontal" style="width:50%" >
<div class="form-group" >
<label class="control-label col-sm-2" for="fname" >First Name:</label>
<div class="col-sm-10">
<input style="width:50%" type="text" class="form-control"
width="50%" id="fname" placeholder="Enter first name"
name="firstname" firstname required [(ngModel)]='objemp.firstname' #firstname="ngModel">
<span class="help-bpx" *ngIf="firstname.touched && !firstname.valid ">Required</span>
</div>
</div>
<div class="form-group" >
<label class="control-label col-sm-2" for="email">Last Name:</label>
<div class="col-sm-10">
<input style="width:50%" required type="text" class="form-control" width="50%"
id="lastname" placeholder="Enter Last Name" name="lastname" lastname required [(ngModel)]='objemp.lastname' #lastname="ngModel">
<span class="help-bpx" *ngIf="lastname.touched && !lastname.valid ">Required</span>
</div>
</div>
<div class="form-group" >
<label class="control-label col-sm-2" for="Gender">Gender:</label>
<div class="col-sm-10">
<select name="gender" gender required [(ngModel)]='objemp.gender' #gender="ngModel">
<option value="0" selected disabled>Please Select</option>
<option value="1">Male</option>
<option value="2">Female</option>
<span class="help-bpx" *ngIf="gender.touched && !gender.valid ">required</span>
</select>
</div>
</div>
<div class="form-group" >
<label class="control-label col-sm-2" for="email">Email:</label>
<div class="col-sm-10">
<input #email="ngModel" style="width:50%" type="email" [(ngModel)]='objemp.email' class="form-control" width="50%" id="email" placeholder="Enter email" name="email">
<span class="help-bpx" *ngIf="email.touched && !email.valid ">**</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button id="btnsubmit" type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
</div>
<button style="display:none" type="button" #closeBtn class="btn btn-default" data-dismiss="modal">Close</button>
Above is the code for the Employee Add Component and template for the same.
Code Description
- Above is the code for the Add Component of the Employee in this we have the import section which is needed for the app.
- In Constructor we have injected the data service and the Router
- We have a function
Register(regForm:NgForm )
Here we are using the template driven approach for adding the employee, so we have declared the form object of type NgForm
- In this Method we are subscribing the
Addemployee
Data service here on success we are showing the alert and redirecting the route to the Home Component - We have
TakeHome
Method Which will emit the method to refresh the parent component and reload the data from there . In Template we have added the Form tag and named the form as #empadd
here in this on NgSubmit
event of the Form we are calling the Register()
which will submit the form to along with its values. - For Validation purpose we are using the basic HTML validation
- Last line we have added the code for the Close Button which is dummy code which will be fired in the template when the Employee is added successfully.
This is About the Add Component lets see the Update component an its template which has same structure and description as that of the Add Component .
employeeupdate.component.ts
import { Component, OnInit, ViewChild, Input, EventEmitter, Output, ElementRef } from '@angular/core';
import { EmployeeDataService } from '../DataService/EmployeeDataService';
import { Router } from '@angular/router';
import { NgForm } from '@angular/forms';
import { Employee } from 'src/Models/Employee';
@Component({
selector: 'app-employeeupdate',
templateUrl: './employeeupdate.component.html',
styleUrls: ['./employeeupdate.component.sass']
})
export class EmployeeupdateComponent implements OnInit {
constructor(private dataservice: EmployeeDataService, private route: Router) {
}
@Output() nameEvent = new EventEmitter<string>();
@ViewChild('closeBtn') cb: ElementRef;
ngOnInit() {
}
@Input() reset: boolean = false;
@ViewChild('regForm') myForm: NgForm;
@Input() isReset: boolean = false;
objtempemp: Employee;
@Input() objemp: Employee = new Employee();
EditEmployee(regForm: NgForm) {
this.dataservice.EditEmployee(this.objemp).subscribe(res => {
alert("Employee updated successfully");
this.nameEvent.emit("ccc");
this.cb.nativeElement.click();
},
}
}
employeeupdate.component.html
<div class="container" style="border:thin">
<form #EditForm='ngForm' name="editform" (ngSubmit)="EditEmployee(EditForm)" class="form-horizontal" style="width:50%">
<div class="form-group">
<label class="control-label col-sm-2" for="fname">First Name:</label>
<div class="col-sm-10">
<input style="width:50%" type="text" class="form-control" width="50%" id="fname" placeholder="Enter first name"
name="firstname" firstname required [(ngModel)]='objemp.firstname' #firstname="ngModel">
<span class="help-bpx" *ngIf="firstname.touched && !firstname.valid ">Required</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="email">Last Name:</label>
<div class="col-sm-10">
<input style="width:50%" required type="text" class="form-control" width="50%" id="lastname" placeholder="Enter Last Name"
name="lastname" lastname required [(ngModel)]='objemp.lastname' #lastname="ngModel">
<span class="help-bpx" *ngIf="lastname.touched && !lastname.valid ">Required</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="Gender">Gender:</label>
<div class="col-sm-10">
<select name="gender" gender required [(ngModel)]='objemp.gender' #gender="ngModel">
<option value="0" selected disabled>Please Select</option>
<option value="1">Male</option>
<option value="2">Female</option>
<span class="help-bpx" *ngIf="gender.touched && !gender.valid ">required</span>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="email">Email:</label>
<div class="col-sm-10">
<input #email="ngModel" style="width:50%" type="email" [(ngModel)]='objemp.email' class="form-control" width="50%"
id="email" placeholder="Enter email" name="email">
<span class="help-bpx" *ngIf="email.touched && !email.valid ">**</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
</div>
<button style="display:none" type="button" #closeBtn class="btn btn-default" data-dismiss="modal">Close</button>
Above is the code for the employee update component description of this component is same as that of the Add component . Lets explore the List component for the clarity
Employeelist.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { EmployeeAddComponent } from '../employee-add/employee-add.component';
import { EmployeeDataService } from '../DataService/EmployeeDataService'
import { Employee } from 'src/Models/Employee'
import { Router } from '@angular/router';
import { EmployeeupdateComponent } from '../employeeupdate/employeeupdate.component';
@Component({
selector: 'app-angular-crud',
templateUrl: './angular-crud.component.html',
styleUrls: ['./angular-crud.component.sass']
})
export class AngularCRUDComponent implements OnInit {
emplist: Employee[];
dataavailbale: Boolean = false;
tempemp: Employee
constructor(private dataservce: EmployeeDataService, private route: Router) {
}
ngOnInit() {
this.LoadData();
}
LoadData() {
this.dataservce.getEmployee().subscribe((tempdate) => {
this.emplist = tempdate;
console.log(this.emplist);
if (this.emplist.length > 0) {
this.dataavailbale = true;
}
else {
this.dataavailbale = false;
}
}
)
, err => {
console.log(err);
}
}
deleteconfirmation(id: string) {
if (confirm("Are you sure you want to delete this ?")) {
this.tempemp = new Employee();
this.tempemp.id = id;
this.dataservce.DeleteEmployee(this.tempemp).subscribe(res => {
alert("Deleted successfully !!!");
this.LoadData();
})
}
}
@ViewChild('empadd') addcomponent: EmployeeAddComponent
@ViewChild('regForm') editcomponent: EmployeeupdateComponent
loadAddnew() {
this.addcomponent.objemp.email = ""
this.addcomponent.objemp.firstname = ""
this.addcomponent.objemp.lastname = ""
this.addcomponent.objemp.id = ""
this.addcomponent.objemp.gender = 0
}
loadnewForm(id: string, email: string, firstname: string, lastname: string, gender: number) {
console.log(gender);
this.editcomponent.objemp.email = email
this.editcomponent.objemp.firstname = firstname
this.editcomponent.objemp.lastname = lastname
this.editcomponent.objemp.id = id
this.editcomponent.objemp.gender = gender
}
RefreshData() {
this.LoadData();
}
}
EmployeeList.html
<div class="container">
<input type="button" class="btn btn-primary" (click)="loadAddnew()" data-toggle="modal" data-target="#myModal" value="Create New">
<hr>
<div *ngIf="!dataavailbale">
<h4> No Employee Data is present Click Add new to add Data.</h4>
</div>
<table class="table" *ngIf="dataavailbale">
<thead>
<tr>
<th scope="col">Sr.No</th>
<th scope="col">First name</th>
<th scope="col">Last Name</th>
<th scope="col">Email</th>
<th scope="col">Gender</th>
<th scope="col" style="align-content: center">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let e of emplist let i = index ">
<td scope="col">{{i+1}}</td>
<td scope="col">{{e.fname}}</td>
<td scope="col">{{e.lname}}</td>
<td scope="col">{{e.email}}</td>
<td scope="col">{{e.gender=="1"?'Male':'Female'}}</td>
<td style="display:none">{{e.id}}</td>
<td scope="col">
<button type="button" class="btn btn-default btn-primary" (click)="loadnewForm(e.id,e.email,e.fname,e.lname,e.gender)"
data-toggle="modal" data-target="#myModaledit">
<span class="glyphicon glyphicon-edit"></span> Edit
</button>
|
<button type="button" class="btn btn-default btn-danger" (click)="deleteconfirmation(e.id)">
<span class="glyphicon glyphicon-trash"></span> Delete
</button>
</td>
</tr>
</tbody>
</table>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-primary">Employee Add</h4>
</div>
<div class="modal-body">
<app-employee-add #empadd (nameEvent)="RefreshData($event)"></app-employee-add>
</div>
<div class="modal-footer">
<button type="button" #closeBtn class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="myModaledit" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Edit</h4>
</div>
<div class="modal-body">
<app-employeeupdate (nameEvent)="RefreshData($event)" [isReset]="resetForm" #regForm></app-employeeupdate>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Code Description
- We are doing some import package that we needed in the component
- Declared variables as per the requirement and in constructor we have imported the Data service and the Router Following are the things which gets us the Reference of the child component which are Added in the Parent component i.e. the Employee list component
@ViewChild('empadd') addcomponent: EmployeeAddComponent
@ViewChild('regForm') editcomponent: EmployeeupdateComponent
- Why we will need this ?? let’s see in next two functions
loadAddnew()
, loadAddnewForm()
, we are using these two viewChild
element where we are resetting and setting the values of the particular form - Next thing we have is the
LoadData()
it subscribes the get, method in the data service and assign the data to the employee list object we have - Delete Employee is called which takes the id from the Table Above and then call the delete service from the Data service and then show alert if it successfully deletes the Employee Data from the database .
- Template code is simple displaying the list of the employee and added add and edit component in the code which will render in the Popup
This was the Components in the Application lets explores Rest of the UI and Front end part for that sake.
Adding Models and Config File
export class Employee{
firstname:string;
lastname:string ;
email:string;
gender:number;
id:string
}
Here is the class which we will use in overall application to send and receive data
Config.ts
This class will hold the Configuration related data right now we have only the App URL in the class but we can have rest of the data here.
Adding Bootstrap popups
We are using the Popups to show the Add and Edit form so as to do this we have the code defined in the Employee List components template.
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-primary">Employee Add</h4>
</div>
<div class="modal-body">
<app-employee-add #empadd (nameEvent)="RefreshData($event)"></app-employee-add>
</div>
<div class="modal-footer">
<button type="button" #closeBtn class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
In this we have used the normal Popup code and inside the modal-body we have rendered out child componets.
Adding Data service
Data service is the layer where we have separated the service calling logic from rest of the application . our data service looks like below,
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Employee } from 'src/Models/Employee'
import { ROOT_URL } from 'src/Models/Config'
import { Observable } from 'rxjs';
@Injectable()
export class EmployeeDataService {
employees: Observable<Employee[]>;
newemployee: Employee;
constructor(private http: HttpClient) {
}
getEmployee() {
return this.http.get<Employee[]>(ROOT_URL + 'Employees');
}
AddEmployee(emp: Employee) {
const headers = new HttpHeaders().set('content-type', 'application/json');
var body = {
Fname: emp.firstname, Lname: emp.lastname, Email: emp.email, gender: emp.gender
}
console.log(ROOT_URL);
return this.http.post<Employee>(ROOT_URL + '/Employees', body, { headers });
}
EditEmployee(emp: Employee) {
console.log(emp);
const params = new HttpParams().set('ID', emp.id);
const headers = new HttpHeaders().set('content-type', 'application/json');
var body = {
Fname: emp.firstname, Lname: emp.lastname, Email: emp.email, ID: emp.id
, gender: emp.gender
}
return this.http.put<Employee>(ROOT_URL + 'Employees/' + emp.id, body, { headers, params })
}
DeleteEmployee(emp: Employee) {
const params = new HttpParams().set('ID', emp.id);
const headers = new HttpHeaders().set('content-type', 'application/json');
var body = {
Fname: emp.firstname, Lname: emp.lastname, Email: emp.email, ID: emp.id
}
return this.http.delete<Employee>(ROOT_URL + '/Employees/' + emp.id)
}
}
In this we have all the methods which will make use of the Httpclient
and Return the observable for each of the Basic http verb like Get, Put, Post and delete, we have imported the basic Http essentials at the Top like HttpParams and HttpClient which is the part of the Angular/Common/http
So far we are done with the Front end design and Implementations of the things let’s move to the server side setup which is done using the .NET Core and Entity Framework core so let’s have a look into it
Back End Web API Development using ASPE.NET Core and Entity Framework Core
In this section let’s explore the API which we use for the implementations of the CRUD operation for the employee this section can be broken down into 4 sections mainly these are how do we setup the .NET core project then setting up the entity framework core and then adding the CORS ( Cross origin resource sharing ) section so that it will allow angular app to communicate with the Server.
Adding .NET Core Web API project
To add .NET core web api project lets follow below steps,
Once we are done with the Adding project let’s move towards the Added Project and do the necessary changes
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Angular7DemoServices;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Angular6DemoServices
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors();
services.AddDbContext<AppDbContext>(opt => opt.UseSqlServer(@"Your connection string"));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMiddleware();
app.UseCors();
app.UseMvc();
}
}
}
This is our startup class where we are configuring the services and registering the services
In this first thing is to Add the Database context where we are using the SQL server as a database
Next thing that we need to do is to configure the CORS Option where we allow the Cross origin resource sharing from the Angular application. Apart from that we have added the Middleware which will again helps us in the CORS issue Middleware code can be like below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace Angular7DemoServices
{
public class CorsMiddleware
{
private readonly RequestDelegate _next;
public CorsMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext httpContext)
{
httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept");
httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
return _next(httpContext);
}
}
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CorsMiddleware>();
}
}
}
This will be the middleware which will add the needed headers in the Request an Response to and from the API . rest part in the Code is nothing but simple CRUD Operation which we are familiar mostly if not we can find it on the Github which will be shared below
So when we Run the web API and the Angular Application we can see the below output as below,
Future Expansion of this article
After seeing the output you might be wondering what these signup and Login button are doing there, so they are for the future expansion so what we would have in that
- Login and Signup with the external authentication like Facebook and Gmail and twitter
- Using Identity server at the Web api end
- Adding new Modules for the employee where they can login and add their daily timesheet
- For the Admin Tracking their daily activities If anyone is interested can contribute to this project which is present at below link.
Source code Link
Here are the Source code link for the Above article
References
https://angular.io/