This is a beginner level article and has been written for novice developers and students who have basic knowledge of programming and want to start learning Angular2, C# and RESTful APIs from scratch. If you are an experienced developer and only need an overview, you can just download the attached project and go through it. You need Visual Studio and SQL Server Management Studio to develop the project along with the article and compile the attached project.
Let's begin...
- Now let’s start the exciting part of writing the
Angular2
code. Before actually writing the code, it is very important to understand the Angular2
architecture, since I am not focusing on writing about Angular2 because you can find plenty of tutorials and free videos about it, let us revise the basic structure of Angular2
if you are lazy enough to go to angular.io website from here:
Modules
: Every Angular app has at least one Angular module class, the root
module. The application is launched by bootstrapping its root module. During development, you're likely to bootstrap the AppModule
in a main.ts file that we will create in next steps. Root module is conventionally named AppModule
. In AppModule
, we specify all components, services or custom pipe filters used by application. Components
: Component controls the view on screen, you can define properties and methods to control the views. If you ever worked with ASP.NET forms, I would say components are like code behind files aspx.cs file where you interact the aspx file through methods and properties. Templates
: You define a component's view with its companion template. A template is a form of HTML that tells Angular how to render the component. It is like an aspx file in ASP.NET form according to my previous step’s example. Metadata
: Metadata tells Angular how to process a class. If you would see the component, it is just a class, MetaData tells what is template (code behind or you can HTML) associated with this component, any style sheet or how to use this component specified through Selector
property. Data binding
: In simple words, how information or control travels between template and component, e.g., when you would click any button in template, how would you get click
event in component and perform your logic. Angular2 provides the following types of data bindings:
{{}} interpolation
displays any variable value declared in component. [ ] property binding
is used to send value from parent component to child component. We will use it in our future chapters. ( ) event binding
is used to get any event from template to component, e.g., (click
).
Directives
: Two kinds of directives exist: structural
and attribute
directives.
- Structural directives alter layout by adding, removing, and replacing elements in DOM, e.g.,
*ngFor
and *ngIf
are used to loop through HTML element and show/hide the element. - Attribute directives alter the appearance or behavior of an existing element. In templates, they look like regular HTML attributes, hence the name, e.g.,
ngStyle
for style sheet, ngModel
for two-way data binding.
- Services: Service is a broad category encompassing any value, function, or feature that your application needs. There is nothing specifically Angular2 about services. Angular2 has no definition of a service. There is no service base class, and no place to register a service. Services example are
Error
, Log
, HTTP
, etc. Component
should only play the facilitator role between template and user. It should delegate rest of the functionality, e.g., fetching data from server, deleting or updating, logging, showing error, etc. to service. - Dependency injection: Dependency injection is a way to supply a new instance of a
class
with the fully-formed dependencies it requires. Most dependencies are services. Angular2 uses dependency injection to provide new components with the services they need. E.g., for HTTP
service, we will use dependency injection to provide the service instance to component in upcoming steps. - For more details and for better understanding, please click here.
- Hopefully, you have got the basic idea about Angular2 architecture, let's create a user management page (
Add
, Update
, Delete
and View
users) using Angular 2 in ASP.NET MVC using RESTFul APIs as backend services. - In our project, we will create all Angular2 related code in app folder as the following convention, if you didn’t create app folder yet, go ahead and create one. If you followed the previous steps, you should have one typescript file main.ts in app folder that we will use to bootstrap the
AppModule
:
- Before moving further, let me show how our final application would look like. It will have two pages, one is home page with only large image and the second will have a table like view with user information, edit and delete button next to each record with one Add button on top of table to add new user. Each button will open modal pop up where you can perform corresponding functionality, following are the screen shots for both pages and each functionality:
- Now you have a basic idea about our final application. Let’s start developing the Angular2 piece of application. Let’s keep the Angular2 architecture in mind and create the basic architecture of application.
- First let's create the Angular2
Module
that would be the entry point of application. Right click on app folder and select Add -> TypeScript File: - If you don’t see the TypeScript File in second menu, right click on app folder, select Add -> New Item, search the TypeScript and select TypeScript file, enter the name and select OK button:
- Enter the name of new TypeScript File as app.module.ts and click on OK button:
- Add the following code in newly added app.module.ts:
import { NgModule } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
@NgModule({
imports: [BrowserModule, ReactiveFormsModule, HttpModule],
declarations: [],
providers: [{ provide: APP_BASE_HREF, useValue: '/' }],
bootstrap: []
})
export class AppModule { }
- Just to refresh your memory, we are using TypeScipt with Angular2. If you want to learn more about TypeScript, click here.
- If you quickly go through
AppModule
class, you can see that we are importing the required libraries, e.g., NgModule
from Angular Core, similarly we will use Reactive forms
for user, we are importing ReactiveFormModule
from Angular Forms package. We will keep extending app.module.ts file by adding user components, service, modal pop up, etc.
- In
NgModule
meta data section:
Imports
contains modules list. Declarations
contain list of components, we will add user components in next steps. Providers
contains the list of services. We will add service with HTTP
operations to perform user read, add, update and delete operations. Right now, it has base href
path. Bootstrap
contains the entry component, we will create app.component.ts file in the next steps and will add it here.
- The next step is to edit the main.ts in app folder and add the following code in it:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
- main.ts code is quite self-explanatory.
AppModule
reference is imported from current folder, making it as entry Module and loading other helper resources (Bootstrapping) for application by using platformBrowserDynamic
module’s bootstrapModule
function. Bootstrap
function initializes the Angular2 application, loads the required components, services or other helping resources to run the application. Try to build the project to avoid any error in next steps. - Next, create two TypeScripts files, app.component.ts and app.routing.ts for main application component and routing table. We will come back to them later, right click on app folder and select Add -> TypeScript File:
- Enter the name app.component.ts and click on OK button:
- Again click on app folder and select Add -> TypeScript File, enter the name app.routing.ts and click on OK button:
- Next, let’s create the Home component with only one large picture:
- We will create all user components in new folder, right click on app folder and select Add -> New Folder, enter the name Components:
- Right click on newly created folder Component and select Add -> TypeScript File:
- Enter the name home.component.ts and click on OK button:
- Add the following code in newly created home.component.ts file:
import { Component } from "@angular/core";
@Component({
template: `<img src="../../images/users.png" style="text-align:center"/>`
})
export class HomeComponent{
}
- In
HomeComponent
, you can see in MetaData’s template property, we have plain HTML image element from root images folder that will show users.png on screen. You can get any picture, save it in images folder and load it in HomeComponent
. - Right click on
Angular2MVC
project and select Add -> New Folder, enter the folder name as images:
- Right click on newly added folder images and select Open Folder in File Explorer, copy the given below image in opened location:
- Our
HomeComponent
is done, let's view it on screen. We need to do few more steps to do that. The first thing we will do is to create the Routing
Table. If you worked with ASP.NET MVC, this routing table is the same as MVC Routing table. We will define custom routes for different view components. In the second step, we will create our main application component where we will create the navigation menu and load all view components.
- Double click on app.routing.ts in app folder to edit it and add the following code:
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './components/home.component';
const appRoutes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent }
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
- In the above code, we are importing the routing libraries from angular router package and recently created
HomeComponent
from components folder. In app Routers, the path
property is actual URL visible in browser address bar, e.g., http://localhost:4500/home. Once we will create the UserComponent
, we will add another route for it. - Next double click on app.component.ts in app folder to edit it and add the following code:
import { Component } from "@angular/core"
@Component({
selector: "user-app",
template: `
<div>
<nav class='navbar navbar-inverse'>
<div class='container-fluid'>
<ul class='nav navbar-nav'>
<li><a [routerLink]="['home']">Home</a></li>
</ul>
</div>
</nav>
<div class='container'>
<router-outlet></router-outlet>
</div>
</div>
`
})
export class AppComponent {
}
AppComponent
is slim one having template with known bootstrap code to create navigation bar with one home link only. The routerlink home name for Home page is what we defined in app.routing.ts’s routing table. You can define whatever is convenient for you, e.g., default, index, etc. router-outlet
acts as place holder for dynamically loaded view components. We also defined selector
property (user-app
) in AppComponent
MetaData section because we will bootstrap AppComponent
in AppModule
and use this selector
in MVC view (index.cshtml) to load it. For more information about router-outlet
, click here. - So we have created the Application Component (
AppComponent
), let’s go to AppModule
and register HomeComponent
and AppComponent
along routing
table. After that, we will add AppComponent
to bootstrap, in order to do this all, update your app.module.ts according to the following:
import { NgModule } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { routing } from './app.routing';
import { HomeComponent } from './components/home.component';
@NgModule({
imports: [BrowserModule, ReactiveFormsModule, HttpModule, routing],
declarations: [AppComponent, HomeComponent],
providers: [{ provide: APP_BASE_HREF, useValue: '/' }],
bootstrap: [AppComponent]
})
export class AppModule { }
- You can see that we imported the
HomeComponent
and AppComponent
, added it in declaration and bootstrapping the AppComponent
as the entry point to our application. (Bootstrapping is more than just an entry point as discussed in the previous steps, you can search on Google to fully understand it. Here for simplicity, I am only referring it as the entry point). - We are almost there to run our Angular2 application and view the Home page. Go to Views -> Home and double click on Index.cshtml to edit it:
- Delete the existing code and enter the following lines of code:
@{
ViewBag.Title = "Index";
}
<body>
<user-app>Loading…</user-app>
</body>
user-app
is the selector
for AppComponent
, this is how we use the Component in HTML:
- Next in Solution Explorer, double click on systemjs.config.js and at the bottom, add main.js in packages section:
- Run the project, you should see the following web application with Home page and large image, you can see in address bar the page URL is ending with home that is the same URL we defined in routing table for Home page:
- So far, we have created basic architecture for Angular2 in ASP.NET MVC application with one static page. The next step is to create the User Management page that includes loading all users, adding new user, updating and deleting existing user:
- In User Management page, we will use TypeScript Interface (for User Model), Reactive forms and one third party component Ng2-Bs3-Modal for modal pop up.
- Interface: An interface is an abstract type, it does not contain any code as a class does. It only defines the signature or shape of an API that’s why we will use interface to define our User Model.
- Reactive Forms: Angular2 provides two kind of forms, Template driven and Reactive Forms (Model Driven Forms). There is a great article available for both forms here & here. if you are ASP.NET MVC developer, Reactive Forms is like MVC strongly typed Razor view.
- Next let's create the user interface. Right click on app folder and select Add -> New Folder. Enter the name of folder as Models:
- Right click on newly created Models folder and select Add -> TypeScript File, enter the file name as user.ts:
- Enter the following variables in newly created user interface:
export interface IUser {
Id: number,
FirstName: string,
LastName: string,
Gender: string
}
- These
interface
properties are same as User
table in database. The awesome thing about Angular2 is, user object will automatically be mapped to array of IUser
interface when we will load data from database through RESTful API, in next steps, we will see how this is being done. - Before moving to
UserComponent
, let's create some helping files, i.e., Global
variables and Enumeration. I prefer to save all endpoints, error message and other shared variables in Global file and I am going to create Enumeration for CRUD operation. Right click on app folder and select Add ->New Folder, name the folder as shared:
- Right click on newly created shared folder and select Add -> TyepScript File, enter the name as global.ts:
- Copy the following code in global.ts:
export class Global {
public static BASE_USER_ENDPOINT = 'api/userapi/';
}
- This is simple
exportable
class with single static
property BASE_USER_ENDPOINT
having the base endpoint for user management RESTful APIs. - Again, right click on shared folder and select Add -> TypeScript File, enter the name as enum.ts:
- Enter the following code in enum.ts file:
export enum DBOperation {
create = 1,
update = 2,
delete =3
}
- Enumeration is quite self-explanatory, instead of hard coded string for CRUD operations (“
create
”, “update
”, ”delete
”), we would use DBOperation
enumeration. - Next, let’s create the important functions to call ASP.NET RESTful Web API for user management using Angular2 HTTP service. As discussed in previous steps, we will create
GET
, POST
, PUT
and DELETE
requests for RESTful users APIs that we already have created using ASP.NET MVC Web API in earlier steps. Right click on app folder and select Add -> New Folder, enter the name as Service
.
- Right click on newly created Service folder and select Add -> TypeScript File, enter the name as user.service.ts:
- Copy the following code in user.service.ts file:
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions} from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
@Injectable()
export class UserService {
constructor(private _http: Http) { }
get(url: string): Observable<any> {
return this._http.get(url)
.map((response: Response) => <any>response.json())
.catch(this.handleError);
}
post(url: string, model: any): Observable<any> {
let body = JSON.stringify(model);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.post(url, body, options)
.map((response: Response) => <any>response.json())
.catch(this.handleError);
}
put(url: string, id: number, model: any): Observable<any> {
let body = JSON.stringify(model);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.put(url+id, body, options)
.map((response: Response) => <any>response.json())
.catch(this.handleError);
}
delete(url: string, id: number): Observable<any> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.delete(url+id,options)
.map((response: Response) => <any>response.json())
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
In order to understand the above code, we need to learn about Observable
, you can easily get information about it just by searching it on Google but I would prefer to quickly go through the following link: https://scotch.io/tutorials/angular-2-http-requests-with-observables
-
In just few lines, Observable
is more like data stream, opposite to promise
method (in Angular 1.x), Observable
doesn’t return the response at once but in stream, it provides very helpful methods, e.g., map
(for mapping result to interface), filter
(filter any particular record from array of data) etc. Observable
also provides HTTP request handling. Rxjs
is an eternal library providing us all Observable
methods.
-
The first method is get
, that is taking the RESTful API URL as a parameter and returning the Observable<any>
, you can also specify the particular type of interface
to return, e.g., Observable<IUser[]>
but I try to keep it generic. In next lines, http get
method is being called by providing the input RESTful API user, calling the map
method to map the JSON response to any
type, you can specify the particular type too like <IUser[]>response.json()
. The type any
is like a dynamic
in C#, it does the compile type check.
- One awesome thing about RESTful API is the HTTP verbs like functions names, i.e., if function name is starting from
GET
, PUT
, POST
or DELETE
, we only need base URL (endpoint), by the HTTP call, it automatically determines the corresponding function. It’s obvious, one Web API controller should have one HTTP verb method. - The other methods
POST
, PUT
and DELETE
have almost same function body, creating the http header and sending the IUser
interface in body where it is being received in Web API controller functions and automatically get converted to user
entity because column name does match. - Now that we created the
user
service, let’s add it to AppModule
. Double click on app.module.ts file in app folder to edit it. Import the UserService
by adding the following line:
import { UserService} from './Service/user.service'
- Add the
UserService
in AppModule
providers section.
- After this, let's create the
UserComponent
. Right click on Components folder and select Add -> TypeScript File:
- Enter the name as user.component.ts:
- We will create the
template
in separate html file so right click on Components folder again select Add-> HTML Page:
- Enter the name as user.component.html:
- Before going to
UserComponent
, let's configure one third party component for modal pop ng2-bs3-modal. It’s very simple to use. - Double click on Package.json file in
Angular2MVC
project and add the following package in devDependencies
section:
"ng2-bs3-modal": "0.10.4"
- Now let’s download this package from NPM, right click on package.json and select Restore Packages:
- Double click on systemjs.config.js in Angular2MVC project:
- Add the following text in map section:
'ng2-bs3-modal': 'npm:/ng2-bs3-modal'
-
Add the following text in packages section:
'ng2-bs3-modal':
{ main: '/bundles/ng2-bs3-modal.js', defaultExtension: 'js' }
- Final update should look like the following:
- Now since we got our modal pop up, let’s create the
UserComponent
that will have view all users, add new user, edit and delete existing users. Double click on user.component.ts file in app -> components folder to edit:
- First add the following
import
statements:
import { Component, OnInit, ViewChild } from '@angular/core';
import { UserService } from '../Service/user.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ModalComponent } from 'ng2-bs3-modal/ng2-bs3-modal';
import { IUser } from '../Models/user';
import { DBOperation } from '../Shared/enum';
import { Observable } from 'rxjs/Rx';
import { Global } from '../Shared/global';
- We are importing
Components
, OnInit
(to use OnInit
event), ViewChild
(to access Modal pop up properties). - Then we are importing the
UserService
that executes the HTTP calls to server. - In
UserComponent
, we are going to use Reactive
(Model-driven) forms that I found way more organized and easy to use than template driven forms. To me, it looks like a strongly type ASP.NET MVC razor view, it is also good for unit testing
. The form fields, validations and validation errors can be managed on TypeScript side and HTML view has minimum form logic that is good practice to keep the code at one place. To read more about Reactive form, click here. ModalComponent
is third party modal pop up that we downloaded in previous steps. IUser
is the interface we will use as a Model, to store the user information. DBOperation
and Global
are enumeration and global variables. Observable
, we briefly discussed in previous steps. We will use subscribe
and filter
function from Rxjs
library. - Next copy the following
Component
meta data information under the import
statements:
@Component({
templateUrl: 'app/Components/user.component.html'
})
- Since
User
is a parent component and we will not use it in any other component, we are not specifying the Selector
property. HTML for User component would be in user.component.html file. - Next let’s start the
UserComponent
class body and declare the required variable:
export class UserComponent implements OnInit
{
@ViewChild('modal') modal: ModalComponent;
users: IUser[];
user: IUser;
msg: string;
indLoading: boolean = false;
userFrm: FormGroup;
dbops: DBOperation;
modalTitle: string;
modalBtnTitle: string;
}
- We are starting our class with
export
and then with our UserComponent
name, since we will use onInit
event, our class must implement this. - The next line is starting with
@ViewChild(‘modal’)
, the modal
is placeholder for Modal pop up component that we will create in HTML template. This is the syntax if you want to access any HTML element in TypeScript. :ModalComponent
specify the type of element. - Next we are creating the array of
IUser
interface to hold the list of users and single User to hold one user information for add, edit and delete. Others are few string and Boolean variables that we will use in next steps to show some messages. - As we discussed in previous steps, we will use
Reactive
(Model-driven) form, so we create the userform
of Formgroup
type. - Next is to add the
constructor
for UserComponent
class:
constructor(private fb: FormBuilder, private _userService: UserService) { }
- On great thing about Angular2 is dependency injection, in constructor you can see, we are getting the
FormBuilder
and UserService
instances though DI. To read more about DI, click here. - So far, our
UserComponent
should look like the following:
- At this point, you might be getting an error because still
ngOnInit
event is not implemented, let’s go ahead and add ngOnInit
event, we will create and initialize our Reactive User form:
ngOnInit(): void {
this.userFrm = this.fb.group({
Id: [''],
FirstName: ['', Validators.required],
LastName: [''],
Gender: ['']
});
this.LoadUsers();
}
- We are initializing the User form, specifying the form elements and validation rules. Right now, form is initialized with empty string ‘’.
- Next let's create the
LoadUsers
method, as name says, this method will call the get
method from UserService
to load all users from database through RESTful API:
LoadUsers(): void {
this.indLoading = true;
this._userService.get(Global.BASE_USER_ENDPOINT)
.subscribe(users => { this.users = users; this.indLoading = false; },
error => this.msg = <any>error);
}
-
Subscribe
is the part of Observable
that we discussed in previous steps. Once the user loads would be complete, it will save it in users
variable. In case of any error, error message would be saved in msg
variable. indLoading
is the Boolean variable we are using here to show loading message until full response would be loaded.
-
Next, let’s add three methods to show modal pop up for Add
, Update
and Delete
user. Add the following code for these functions:
addUser() {
this.dbops = DBOperation.create;
this.SetControlsState(true);
this.modalTitle = "Add New User";
this.modalBtnTitle = "Add";
this.userFrm.reset();
this.modal.open();
}
editUser(id: number) {
this.dbops = DBOperation.update;
this.SetControlsState(true);
this.modalTitle = "Edit User";
this.modalBtnTitle = "Update";
this.user = this.users.filter(x => x.Id == id)[0];
this.userFrm.setValue(this.user);
this.modal.open();
}
deleteUser(id: number) {
this.dbops = DBOperation.delete;
this.SetControlsState(false);
this.modalTitle = "Confirm to Delete?";
this.modalBtnTitle = "Delete";
this.user = this.users.filter(x => x.Id == id)[0];
this.userFrm.setValue(this.user);
this.modal.open();
}
-
All these methods are resembling so let’s take AddUser
method and understand it. First, we are storing current DB operation in dpops
variable that is of DBOperation
enumeration type. Next, we are calling SetControlsState
method that will enable or disable form controls. Next variables are setting the modal pop up heading and button title. In only AddUser
function, we are resetting form to clearing the form. Next, we are calling modal.open()
function to view the modal pop up. In edit and delete user method, we are getting UserID
as parameter, calling the Observable
’s filter method to get single user from users list. The filter syntax is like anonymous method in C#. The next line is to assign the single user to user form that will set the value to the front end, piece of cake.
-
Let’s create the SetControlsState
that will enable or disable the form. Reactive
form has enable
and disable
methods that make the control read-only and editable.
SetControlsState(isEnable: boolean)
{
isEnable ? this.userFrm.enable() : this.userFrm.disable();
}
-
The next method is onSubmit
that actually get the form values and based on DBOperation
enumeration value, it performs add, update and delete operation, we are using simple switch
statement, paste the following code:
onSubmit(formData: any) {
this.msg = "";
switch (this.dbops) {
case DBOperation.create:
this._userService.post(Global.BASE_USER_ENDPOINT, formData._value).subscribe(
data => {
if (data == 1)
{
this.msg = "Data successfully added.";
this.LoadUsers();
}
else
{
this.msg = "There is some issue in saving records,
please contact to system administrator!"
}
this.modal.dismiss();
},
error => {
this.msg = error;
}
);
break;
case DBOperation.update:
this._userService.put(Global.BASE_USER_ENDPOINT,
formData._value.Id, formData._value).subscribe(
data => {
if (data == 1)
{
this.msg = "Data successfully updated.";
this.LoadUsers();
}
else {
this.msg = "There is some issue in saving records,
please contact to system administrator!"
}
this.modal.dismiss();
},
error => {
this.msg = error;
}
);
break;
case DBOperation.delete:
this._userService.delete(Global.BASE_USER_ENDPOINT,
formData._value.Id).subscribe(
data => {
if (data == 1)
{
this.msg = "Data successfully deleted.";
this.LoadUsers();
}
else {
this.msg = "There is some issue in saving records,
please contact to system administrator!"
}
this.modal.dismiss();
},
error => {
this.msg = error;
}
);
break;
}
}
-
The code is quite simple and self-explanatory, once we submit the form, it sends all the values that we can get through .value
property. That’s pretty much it on the TypeScript side.
-
Let’s write the HTML template for UserComponent
. Double click on user.component.html to edit it:
-
Copy the following code in user.component.html:
<div class='panel panel-primary'>
<div class='panel-heading'>
User Management
</div>
<div class='panel-body'>
<div class='table-responsive'>
<div style="padding-bottom:10px"><button class="btn btn-primary"
(click)="addUser()">Add</button></div>
<div class="alert alert-info" role="alert"
*ngIf="indLoading"><img src="../../images/loading.gif"
width="32" height="32" /> Loading...</div>
<div *ngIf='users && users.length==0'
class="alert alert-info" role="alert">No record found!</div>
<table class='table table-striped' *ngIf='users && users.length'>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Gender</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users">
<td>{{user.FirstName}}</td>
<td>{{user.LastName}}</td>
<td>{{user.Gender}}</td>
<td>
<button title="Edit" class="btn btn-primary"
(click)="editUser(user.Id)">Edit</button>
<button title="Delete" class="btn btn-danger"
(click)="deleteUser(user.Id)">Delete</button>
</td>
</tr>
</tbody>
</table>
<div>
</div>
</div>
<div *ngIf="msg" role="alert"
class="alert alert-info alert-dismissible">
<button type="button" class="close"
data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span></button>
<span class="glyphicon glyphicon-exclamation-sign"
aria-hidden="true"></span>
<span class="sr-only">Error:</span>
{{msg}}
</div>
</div>
</div>
<modal #modal>
<form novalidate (ngSubmit)="onSubmit(userFrm)" [formGroup]="userFrm">
<modal-header [show-close]="true">
<h4 class="modal-title">{{modalTitle}}</h4>
</modal-header>
<modal-body>
<div class="form-group">
<div>
<span>Full name*</span>
<input type="text" class="form-control"
placeholder="First Name" formControlName="FirstName">
</div>
<div>
<span>Full name</span>
<input type="text" class="form-control"
placeholder="Last Name" formControlName="LastName">
</div>
<div>
<span>Gender*</span>
<select formControlName="Gender" class="form-control">
<option>Male</option>
<option>Female</option>
</select>
</div>
</div>
</modal-body>
<modal-footer>
<div>
<a class="btn btn-default" (click)="modal.dismiss()">Cancel</a>
<button type="submit" [disabled]="userFrm.invalid"
class="btn btn-primary">{{modalBtnTitle}}</button>
</div>
</modal-footer>
</form>
</modal>
-
If you look at the Add button, we are calling the AddUser
function by using (click)
function that is the example of event
binding we discussed in previous steps.
-
Next, we are using *ngIf
, the structural directives
to show the loading message based on indLoading
Boolean variable.
-
Next, we are using *ngFor
structural directive to loop through the users
array and showing the user information.
-
Next code is for modal pop up, you can see #modal
placeholder that we are using to access it on TypeScript side through @ViewChild
to access open and dismiss functions.
-
Next we are creating the form, (ngSumbit)
event will send the form data to TypeScript onSumit
function.
-
Through [formgorup]
property binding, we are assigning the userform
that we created on TypeScript side. We are telling our template the corresponding form control through formControlName
property.
-
Add and Edit buttons will be disabled until form gets valid. This is being handled by [disabled]
property binding until userform.invalid
property get enabled.
-
That’s it with UserComponent
, now let’s add the routing for UserComponent
and add to it AppModule
.
-
Double click on app.routing.ts in app folder to edit it:
-
Import the UserComponent
by the following code:
import { UserComponent } from './components/user.component';
-
Add the UserComponent
route as follows:
{ path: 'user', component: UserComponent }
The final app.routing.ts should look like the following:
-
Edit the app.component.ts by double clicking on it:
-
Add User Component in App Module:
import { UserComponent } from './components/user.component';
-
Add the UserComponent
in declaration section, the final AppModule
should look like the following:
-
Add menu item for User Management, double click on app.component.ts and add the following line:
<li><a [routerLink]="['user']">Users Management</a></li>
-
Final app.component.ts should be as follows:
-
Compile and run the application.