If you missed the previous article in this series please go and have an overview before getting into this part.
Introduction
In our previous article we saw an overview on AngularJS. Now we know what AngularJS is capable of, what is it, and how to start with it. Now it’s time to make a sample application which can perform CRUD operations using database. Ok, let's get started.
AngularJS with Visual Studio
Let’s open Visual Studio 2015(IDE) click: File, New, then Project. After that a new window will appear like the following image.
Figure 1.0
Click on ASP.NET Web Application, rename the application and hit “OK” button at bottom right. Choose empty template in next window and click on “ok” button. It will take a while to load a sample empty project.
Now the first thing we need to do is register AngularJS.Core in this application. We need to get reference from NuGet.
To do that right click on project name and click on “Manage NuGet Packages” like the following image,
Figure 1.1
And in next window browse searching “Angular” and install the updated version of AngularJS.Core like the following image.
Figure 1.2
Or click on Tools, NuGet Package Manager > Package Manager Console and write Install-Package AngularJS.Core.
Also we need to add jQuery library in our project like below.
Figure 1.3
Our installation process is done. Now test it with our previous AngularJS code in comparsion with jQuery section.
Data Layer
- public class GenericRepository < T > : IRepository < T > whereT: class
- {
- CRUD_SampleEntities context = null;
- private DbSet < T > entities = null;
- public GenericRepository(CRUD_SampleEntities context)
- {
- this.context = context;
- entities = context.Set < T > ();
- }
-
-
-
-
- public IEnumerable < T > ExecuteQuery(stringspQuery, object[] parameters)
- {
- using(context = newCRUD_SampleEntities())
- {
- returncontext.Database.SqlQuery < T > (spQuery, parameters).ToList();
- }
- }
-
-
-
-
- public TExecuteQuerySingle(stringspQuery, object[] parameters)
- {
- using(context = newCRUD_SampleEntities())
- {
- returncontext.Database.SqlQuery < T > (spQuery, parameters).FirstOrDefault();
- }
- }
-
-
-
-
- public int ExecuteCommand(stringspQuery, object[] parameters)
- {
- int result = 0;
- try
- {
- using(context = newCRUD_SampleEntities())
- {
- result = context.Database.SqlQuery < int > (spQuery, parameters).FirstOrDefault();
- }
- }
- catch
- {}
- return result;
- }
- private bool disposed = false;
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposed)
- {
- if (disposing)
- {
- context.Dispose();
- }
- }
- this.disposed = true;
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
Interface:
- interface IRepository<T> : IDisposablewhereT : class
- {
- IEnumerable<T>ExecuteQuery(stringspQuery, object[] parameters);
- TExecuteQuerySingle(stringspQuery, object[] parameters);
- intExecuteCommand(stringspQuery, object[] parameters);
- }
Code Explanation:
If you are new to this design pattern overview click here for
more.
Middle Layer: - public partial class CustomerService
- {
- private GenericRepository < Customer > CustRepository;
- public CustomerService()
- {
- this.CustRepository = newGenericRepository < Customer > (newCRUD_SampleEntities());
- }
- public IEnumerable < Customer > GetAll(object[] parameters)
- {
- stringspQuery = "[Get_Customer] {0}";
- returnCustRepository.ExecuteQuery(spQuery, parameters);
- }
- public CustomerGetbyID(object[] parameters)
- {
- stringspQuery = "[Get_CustomerbyID] {0}";
- returnCustRepository.ExecuteQuerySingle(spQuery, parameters);
- }
- public int Insert(object[] parameters)
- {
- stringspQuery = "[Set_Customer] {0}, {1}";
- returnCustRepository.ExecuteCommand(spQuery, parameters);
- }
- public int Update(object[] parameters)
- {
- stringspQuery = "[Update_Customer] {0}, {1}, {2}";
- returnCustRepository.ExecuteCommand(spQuery, parameters);
- }
- public int Delete(object[] parameters)
- {
- stringspQuery = "[Delete_Customer] {0}";
- returnCustRepository.ExecuteCommand(spQuery, parameters);
- }
- }
Our Data Layer and Service layer is ready. For creating database, please download the database script and execute it using MS SQL Server.
Let’s create a MVC HomeController and generate empty view.
Figure: 1.4 MVC HomeController Code Explanation
Let’s explaine the code part by part.
Get All Records: Below code sample is to get all records from database by using our middle layer/service layer. We are returning JSON data here. The format of JSON data is easy to read, follow attribute-value pairs.
Initially we are getting ten (10) records, this is plan for paging in view page.
-
- [HttpGet]
- public JsonResultGetAllData()
- {
- int Count = 10;
- IEnumerable < object > customers = null;
- try
- {
- object[] parameters = {
- Count
- };
- customers = objCust.GetAll(parameters);
- }
- catch
- {}
- return Json(customers.ToList(), JsonRequestBehavior.AllowGet);
- }
While we are returning the list data we have set “
JsonRequestBehavior.AllowGet”. if we miss that, this error message will appear:
“
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.”
Why use it? If you read that message carefully the answer is there. This is for security reasons.
Get Single Record Details: Below code sample will retrieve a single selected record details from database, which also returning JSON data format.
-
- [HttpGet]
- public JsonResultGetbyID(int id)
- {
- object customer = null;
- try
- {
- object[] parameters = {
- id
- };
- customer = this.objCust.GetbyID(parameters);
- }
- catch
- {}
- return Json(customer, JsonRequestBehavior.AllowGet);
- }
Insert Records: Below code sample will Insert/save record details to database, which is returning a JSON result of boolean data type.
If it’s true then it indicate that data inserted to database successfully.
-
- [HttpPost]
- public JsonResult Insert(Customer model)
- {
- int result = 0;
- bool status = false;
- if (ModelState.IsValid)
- {
- try
- {
- object[] parameters = {
- model.CustName,
- model.CustEmail
- };
- result = objCust.Insert(parameters);
- if (result == 1)
- {
- status = true;
- }
- return Json(new
- {
- success = status
- });
- }
- catch
- {}
- }
- return Json(new
- {
- success = false,
- errors = ModelState.Keys.SelectMany(i => ModelState[i].Errors).Select(m => m.ErrorMessage).ToArray()
- });
- }
Update Records: Below code sample will update existing record details to database that is selected to update, which is also returning a JSON result of boolean data type.
If it’s true then it indicate that data updated to database successfully.
-
- [HttpPost]
- public JsonResult Update(Customer model)
- {
- int result = 0;
- bool status = false;
- if (ModelState.IsValid)
- {
- try
- {
- object[] parameters = {
- model.Id,
- model.CustName,
- model.CustEmail
- };
- result = objCust.Update(parameters);
- if (result == 1)
- {
- status = true;
- }
- return Json(new
- {
- success = status
- });
- }
- catch
- {}
- }
- return Json(new
- {
- success = false,
- errors = ModelState.Keys.SelectMany(i => ModelState[i].Errors).Select(m => m.ErrorMessage).ToArray()
- });
- }
Delete Records: Below code sample will delete existing record details to database that is selected to delete, which is also returning a JSON result of boolean data type.
If it’s true then it indicate that data deleted from database successfully.
-
- [HttpDelete]
- public JsonResult Delete(int id)
- {
- int result = 0;
- bool status = false;
- try
- {
- object[] parameters = {
- id
- };
- result = objCust.Delete(parameters);
- if (result == 1)
- {
- status = true;
- }
- }
- catch
- {}
- return Json(new
- {
- success = status
- });
- }
We are done with our MVC Controller to perform CRUD operations on database. Now let’s move on to next part, the AngularJS part.
AngularJS(JavaScript) Controller - angular.module('myFormApp', []).controller('CustomerController', function ($scope, $http, $location, $window)
- {
- $scope.custModel = {};
- $scope.message = '';
- $scope.result = "color-default";
- $scope.isViewLoading = false;
- $scope.ListCustomer = null;
- getallData();
-
- function getallData()
- {
-
- $http.get('/Home/GetAllData').success(function (data, status, headers, config)
- {
- $scope.ListCustomer = data;
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- };
-
- $scope.getCustomer = function (custModel)
- {
- $http.get('/Home/GetbyID/' + custModel.Id).success(function (data, status, headers, config)
- {
-
- $scope.custModel = data;
- getallData();
- console.log(data);
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- };
-
- $scope.saveCustomer = function ()
- {
- $scope.isViewLoading = true;
- $http(
- {
- method: 'POST',
- url: '/Home/Insert',
- data: $scope.custModel
- }).success(function (data, status, headers, config)
- {
- $scope.errors = [];
- if (data.success === true)
- {
- $scope.message = 'Form data Saved!';
- $scope.result = "color-green";
- getallData();
- $scope.custModel = {};
- console.log(data);
- }
- else
- {
- $scope.errors = data.errors;
- }
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- getallData();
- $scope.isViewLoading = false;
- };
-
- $scope.updateCustomer = function ()
- {
-
- $scope.isViewLoading = true;
- $http(
- {
- method: 'POST',
- url: '/Home/Update',
- data: $scope.custModel
- }).success(function (data, status, headers, config)
- {
- $scope.errors = [];
- if (data.success === true)
- {
- $scope.custModel = null;
- $scope.message = 'Form data Updated!';
- $scope.result = "color-green";
- getallData();
- console.log(data);
- }
- else
- {
- $scope.errors = data.errors;
- }
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- $scope.isViewLoading = false;
- };
-
- $scope.deleteCustomer = function (custModel)
- {
-
- varIsConf = confirm('You are about to delete ' + custModel.CustName + '. Are you sure?');
- if (IsConf)
- {
- $http.delete('/Home/Delete/' + custModel.Id).success(function (data, status, headers, config)
- {
- $scope.errors = [];
- if (data.success === true)
- {
- $scope.message = custModel.CustName + ' deleted from record!!';
- $scope.result = "color-red";
- getallData();
- console.log(data);
- }
- else
- {
- $scope.errors = data.errors;
- }
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- }
- };
- }).config(function ($locationProvider)
- {
- $locationProvider.html5Mode(true);
- });
Code Explanation
$http is core AngularJS service that can communicate with the remote HTTP servers. HTTP methods that participate used to communicate:
- $http.get: get data
- $http.post: post new data
- $http.put: update existing data
- $http.delete: delete existing data
Know more about $http service here.
Get All Record: Using $http.get method we are retrieving all records from database.
-
- function getallData()
- {
-
- $http.get('/Home/GetAllData').success(function (data, status, headers, config)
- {
- $scope.ListCustomer = data;
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- };
Get Single Record: Here we are retrieving existing customer records from database. The
$scope.getCustomer method is getting called while edit button is getting hit/click.
-
- $scope.getCustomer = function (custModel)
- {
- $http.get('/Home/GetbyID/' + custModel.Id).success(function (data, status, headers, config)
- {
-
- $scope.custModel = data;
- getallData();
- console.log(data);
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- };
Using $http.get method we are retrieving selected customer record from database by passing the Customer ID to MVC Controller update method.
In return we are getting the query data and AngularJS $scope.custModel is binding the data to input model using ng-model, we know AngularJS support Two-way Data Binding.
Know more about Two-way Data Binding
here.
Save Record: Here we are saving customer records. The $scope.saveCustomer method is getting called from UI when we submit the form with customer information by clicking the submit button.
Using $http.post we are passing the customer object to our MVC controller.
-
- $scope.saveCustomer = function ()
- {
- $scope.isViewLoading = true;
- $http(
- {
- method: 'POST',
- url: '/Home/Insert',
- data: $scope.custModel
- }).success(function (data, status, headers, config)
- {
- $scope.errors = [];
- if (data.success === true)
- {
- $scope.message = 'Form data Saved!';
- $scope.result = "color-green";
- getallData();
- $scope.custModel = {};
- console.log(data);
- }
- else
- {
- $scope.errors = data.errors;
- }
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- getallData();
- $scope.isViewLoading = false;
- };
The controller is doing the rest with a retun status of saved? or Not. After successful insertion we have reload (calling getallData() method again) the data table.
Edit Record: Here we are updating existing customer records to the database. The $scope.updateCustomer method is getting called while update button is getting hit/click.
Like save record, same thing also happening here. The main difference in saving and updating is the Cutomer ID. This time we are passing Customer ID with customer object which is getting from a hidden input field.
- <input type="hidden" ng-model="custModel.Id" name="cid" />
Using $http.post we are passing the customer object to our MVC controller.
-
- $scope.updateCustomer = function ()
- {
-
- $scope.isViewLoading = true;
- $http(
- {
- method: 'POST',
- url: '/Home/Update',
- data: $scope.custModel
- }).success(function (data, status, headers, config)
- {
- $scope.errors = [];
- if (data.success === true)
- {
- $scope.custModel = null;
- $scope.message = 'Form data Updated!';
- $scope.result = "color-green";
- getallData();
- console.log(data);
- }
- else
- {
- $scope.errors = data.errors;
- }
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- $scope.isViewLoading = false;
- };
The controller is doing the rest with a retun status of updated? or Not. After successful updating we have reload(calling getallData() method again) the data table.
Delete Record: Here we are deleting existing customer records from database. The
$scope.deleteCustomer method is getting called while delete button is getting hit/click.
-
- $scope.deleteCustomer = function (custModel)
- {
-
- varIsConf = confirm('You are about to delete ' + custModel.CustName + '. Are you sure?');
- if (IsConf)
- {
- $http.delete('/Home/Delete/' + custModel.Id).success(function (data, status, headers, config)
- {
- $scope.errors = [];
- if (data.success === true)
- {
- $scope.message = custModel.CustName + ' deleted from record!!';
- $scope.result = "color-red";
- getallData();
- console.log(data);
- }
- else
- {
- $scope.errors = data.errors;
- }
- }).error(function (data, status, headers, config)
- {
- $scope.errors = [];
- $scope.message = 'Unexpected Error while saving data!!';
- console.log($scope.message);
- });
- }
- };
Let’s get into UI/View section. Here’s the Index view where we perform CRUD operations graphically.
Html View - @{
- ViewBag.Title = "Index";
- }
-
-
- <h2>Create Customer</h2>
- <div id="content"ng-controller="CustomerController">
- <span ng-show="isViewLoading"class="viewLoading">
- <img src="~/Content/images/ng-loader.gif"/> loading...
-
- </span>
- <div ng-class="result">{{message}}
- </div>
- <hr/>
- <form name="frmCustomer"novalidate>
- <div>
- <input type="hidden"ng-model="custModel.Id"name="cid"/>
- </div>
- <div>
- <label for="email">Customer Name
- </label>
- <input type="text"ng-model="custModel.CustName"name="cname"placeholder=""requiredng-minlength="4"ng-maxlength="14"/>
- <span class="error"ng-show="(frmCustomer.$dirty||submitted)&&frmCustomer.cname.$error.required">Customer name is Required
- </span>
- <span class="error"ng-show="frmCustomer.$dirty&&frmCustomer.cname.$error.minlength">Minimum length required is 5
- </span>
- <span class="error"ng-show="frmCustomer.$dirty&&frmCustomer.cname.$error.maxlength">Minimum length required is 15
- </span>
- </div>
- <div>
- <label for="email">E-mail address
- </label>
- <input type="email"ng-model="custModel.CustEmail"name="email"placeholder=""required/>
- <span class="error"ng-show="(frmCustomer.$dirty||submitted)&&frmCustomer.email.$error.required">EmailId is Required!
- </span>
- <span class="error"ng-show="(frmCustomer.$dirty||submitted)&&frmCustomer.$error.email">Invalid EmailId!
- </span>
- </div>
- <div class="btn">
- <input type="submit"value="Save"ng-click="saveCustomer()"ng-disabled="frmCustomer.$invalid">
- <input type="submit"value="Update"ng-click="updateCustomer()"ng-disabled="frmCustomer.$invalid">
- </div>
- </form>
- <hr/>
- <h2>All Customers</h2>
- <table class="table table-striped">
- <trng-repeat="custModelinListCustomer">
- <td>{{custModel.Id}}</td>
- <td>{{custModel.CustName}}</td>
- <td>{{custModel.CustEmail}}</td>
- <td>
- <a href="#"ng-click="getCustomer(custModel)"title="Edit Record">
- <imgsrc="~/Content/images/edit.png"/>
- </a>
- <a href="#"ng-click="deleteCustomer(custModel)"title="Delete Record">
- <imgsrc="~/Content/images/erase.png"/>
- </a>
- </td>
- </tr>
- </table>
- </div>
-
- @section JavaScript{
-
- <script src="~/Scripts/angular.js">
- </script>
- <script src="~/ScriptsNg/CustomerController.js">
- </script>
- }
Code Explanation
Below code sample is a table with repeating table row(<tr>). Here, ng-repeat is displaying single record(custModel ) with it’s template once per record from ListCustomer, or simply working as a repeater of table row.
Know more about ng-repeat
here.
- <table class="table table-striped">
- <trng-repeat="custModelinListCustomer">
- <td>{{custModel.Id}}</td>
- <td>{{custModel.CustName}}</td>
- <td>{{custModel.CustEmail}}</td>
- <td>
- <ahref="#" ng-click="getCustomer(custModel)" title="Edit Record">
- <img src="~/Content/images/edit.png" /> </a>
- <a href="#" ng-click="deleteCustomer(custModel)" title="Delete Record">
- <imgsrc="~/Content/images/erase.png" /> </a>
- </td>
- </tr>
- </table>
We are almost done. Let’s style our UI with CSS, below is css that we used to style the UI.
Form Style - #content label
- {
- width: 150 px;
- }.btn
- {
- margin - left: 140 px;
- }#conten tinput[type = submit]
- {
- width: 85 px;
- padding: 5 px15px;
- background: #ff6a00;
- border: 0 none;
- cursor: pointer;
- color: #fff;
- }.error
- {
- color: red;
- }.color -
- default
- {
- color: #000;
- }
-
- .color-red {
- color: red;
- }
-
- .color-green {
- color: green;
- }
-
- # contentinput.ng - dirty.ng - invalid
- {
- border: 1 pxsolidred;
- background - color: rgb(255, 244, 244);
- }
- [ng\: cloak],
- [ng - cloak],
- [data - ng - cloak],
- [x - ng - cloak],
- .ng - cloak,
- .x - ng - cloak
- {
- display: none!important;
- }
Hide Directive Flash (ng-cloak)
While loading our page you may noticed that Angular html template are visible/flash. It happened while the browser in its compilation process of Angular html template, usually it flash while the page is loading. Which can hide using “
ng-cloak/data-ng-cloak” directive.
Know more about ng-cloak
here.
We also need to add css class in our application start point
.<body ng-app="myFormApp" class="ng-cloak">. Below is the css class of using ng-cloak.
- [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
- display: none!important;
- }
Let’s put a breakpoint on Updater() method in HomeController and run it, after submitting the form it’ll hit the breakpoint.
In debug mode we can see the model is populated with form data. We can also debug using browser by putting debugger in our script.
- $scope.updateCustomer = function () {
- debugger;
- };
In debug mode in our browser we can see the
$scope.custModel is populated with form data, which is going to update the selected record in database.
Output [Browser: Inspect > Console]
[Browser: Inspect > Network]
Hope that this will help you to learn AngularJS.
Points of Interest
In the next part we will make a Single Page Application(SPA) based on this Application to maintain the flow, and focus on AngularJS Routing.