After huge demand of my readers for this article, finally I get a chance to write this article. In this article, you will learn CRUD operations with model dialog using UI-Grid and Web API. This article describes how to load data in ui-grid and add new record using model dialog and update existing record and delete using model dialog.
Read the below articles first to understand the AngularJS UI-grid.
In this article, I am going to use stored procedure.
ADO.NET Entity Data Model
![]()
Stored Procedures
- USE [NORTHWND]
- GO
-
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE PROCEDURE [dbo].[AddEmployee]
- --DECLARE
- @FirstName varchar(100) = NULL,
- @LastName varchar(200) = NULL,
- @City varchar(50) = NULL,
- @Region varchar(50) = NULL,
- @PostalCode varchar(10) = NULL,
- @Country varchar(50) = NULL,
- @Notes text = NULL
- AS
- BEGIN
- BEGIN TRANSACTION
- BEGIN TRY
- INSERT INTO Employees (FirstName, LastName, City, Region, PostalCode, Country, Notes)
- VALUES (@FirstName, @LastName, @City, @Region, @PostalCode, @Country, @Notes)
- END TRY
- BEGIN CATCH
- --SELECT ERROR_NUMBER() AS ErrorNumber
- -- ,ERROR_SEVERITY() AS ErrorSeverity
- -- ,ERROR_STATE() AS ErrorState
- -- ,ERROR_PROCEDURE() AS ErrorProcedure
- -- ,ERROR_LINE() AS ErrorLine
- -- ,ERROR_MESSAGE() AS ErrorMessage;
- END CATCH
- COMMIT TRANSACTION
- END
- GO
-
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE PROCEDURE [dbo].[DeleteEmployee]
- --DECLARE
- @EmployeeID int
- AS
- BEGIN
- BEGIN TRANSACTION
- BEGIN TRY
- DELETE FROM Employees WHERE EmployeeID = @EmployeeID
- END TRY
- BEGIN CATCH
- --SELECT ERROR_NUMBER() AS ErrorNumber
- -- ,ERROR_SEVERITY() AS ErrorSeverity
- -- ,ERROR_STATE() AS ErrorState
- -- ,ERROR_PROCEDURE() AS ErrorProcedure
- -- ,ERROR_LINE() AS ErrorLine
- -- ,ERROR_MESSAGE() AS ErrorMessage;
- END CATCH
- COMMIT TRANSACTION
- END
- GO
-
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE PROCEDURE [dbo].[GetEmployee]
- AS
- SELECT EmployeeID,
- FirstName,
- LastName,
- City,
- Region,
- PostalCode,
- Country,
- Notes
- FROM Employees
- ORDER BY EmployeeID DESC
- GO
-
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE PROCEDURE [dbo].[UpdateEmployee]
- --DECLARE
- @EmployeeID int,
- @FirstName varchar(100) = NULL,
- @LastName varchar(200) = NULL,
- @City varchar(50) = NULL,
- @Region varchar(50) = NULL,
- @PostalCode varchar(10) = NULL,
- @Country varchar(50) = NULL,
- @Notes text = NULL
- AS
- BEGIN
- BEGIN TRANSACTION
- BEGIN TRY
- UPDATE Employees
- SET FirstName = @FirstName, LastName = @LastName,
- City=@City, Region=@Region, PostalCode=@PostalCode,
- Country=@Country, Notes = @Notes
- WHERE EmployeeID = @EmployeeID
- END TRY
- BEGIN CATCH
- --SELECT ERROR_NUMBER() AS ErrorNumber
- -- ,ERROR_SEVERITY() AS ErrorSeverity
- -- ,ERROR_STATE() AS ErrorState
- -- ,ERROR_PROCEDURE() AS ErrorProcedure
- -- ,ERROR_LINE() AS ErrorLine
- -- ,ERROR_MESSAGE() AS ErrorMessage;
- END CATCH
- COMMIT TRANSACTION
- END
- GO
Model Class
- public class Employee
- {
- public int EmployeeID { get; set; }
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public string City { get; set; }
- public string Region { get; set; }
- public string PostalCode { get; set; }
- public string Country { get; set; }
- public string Notes { get; set; }
- }
Builder
- public class EmployeeVMBuilder
- {
-
- public NORTHWNDEntities db = new NORTHWNDEntities();
-
-
-
-
- public async Task<IEnumerable<GetEmployee_Result>> GetEmployee()
- {
- try
- {
- return await db.Database.SqlQuery<GetEmployee_Result>("GetEmployee").ToListAsync();
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
-
-
-
-
- public void UpdateEmployee(GetEmployee_Result saveData)
- {
- try
- {
- db.UpdateEmployee(saveData.EmployeeID, saveData.FirstName, saveData.LastName, saveData.City, saveData.Region, saveData.PostalCode, saveData.Country, saveData.Notes);
- db.SaveChanges();
- }
- catch (Exception)
- {
- throw;
- }
- }
-
-
-
-
- public void DeleteEmployee(int EmployeeID)
- {
- try
- {
- db.DeleteEmployee(EmployeeID);
- db.SaveChanges();
- }
- catch (Exception)
- {
- throw;
- }
- }
-
-
-
-
- public void AddEmployee(GetEmployee_Result saveData)
- {
- try
- {
- db.AddEmployee(saveData.FirstName, saveData.LastName, saveData.City, saveData.Region, saveData.PostalCode, saveData.Country, saveData.Notes);
- db.SaveChanges();
- }
- catch (Exception)
- {
- throw;
- }
- }
- }
Web API
- [RoutePrefix("api/EmployeeAPI")]
- public class EmployeeAPIController : ApiController
- {
- private readonly EmployeeVMBuilder _employeeVMBuilder = new EmployeeVMBuilder();
-
- [Route("GetEmployee")]
- public async Task<IEnumerable<GetEmployee_Result>> GetEmployee()
- {
- return await _employeeVMBuilder.GetEmployee();
- }
- [Route("UpdateEmployee")]
- public void UpdateEmployee(GetEmployee_Result saveData)
- {
- _employeeVMBuilder.UpdateEmployee(saveData);
- }
- [Route("AddEmployee")]
- public void AddEmployee(GetEmployee_Result saveData)
- {
- _employeeVMBuilder.AddEmployee(saveData);
- }
- [HttpGet]
- [Route("DeleteEmployee")]
- public void DeleteEmployee(int EmployeeID)
- {
- _employeeVMBuilder.DeleteEmployee(EmployeeID);
- }
- }
Thus, we are done with Entity framework and API Controller here. Now, install the files given below, using "Manage NuGet Package".
![]()
Add JavaScript files and CSS reference in BundleConfig.cs.
- bundles.Add(new StyleBundle("~/Content/css").Include(
- "~/Content/bootstrap.css",
- "~/Content/site.css",
- "~/Content/ui-grid.min.css"));
- bundles.Add(new ScriptBundle("~/bundles/angular").Include(
- "~/Scripts/angular.js",
- "~/Scripts/angular-route.js",
- "~/Scripts/ui-grid.js",
- "~/Scripts/angular-ui/ui-bootstrap.js",
- "~/Scripts/angular-ui/ui-bootstrap-tpls.js"));
- bundles.Add(new ScriptBundle("~/bundles/employee").Include(
- "~/Angular/app.js",
- "~/Angular/Services/employeeService.js",
- "~/Angular/Controller/employeeController.js",
- "~/Angular/Controller/editEmployeeController.js",
- "~/Angular/Controller/addEmployeeController.js"));
And render on _layout.cshtml.
- @Scripts.Render("~/bundles/jquery")
- @Scripts.Render("~/bundles/bootstrap")
- @Scripts.Render("~/bundles/angular")
- @Scripts.Render("~/bundles/employee")
- @RenderSection("scripts", required: false)
Now, add a new Angular Controller with scope. I am using just one script for Module, Service, and Controller. You can have it separate if working on a big project.
Module
-
- var app = angular.module('app', ['ngRoute',
- 'ui.grid',
- 'ui.grid.edit',
- 'ui.grid.pagination',
- 'ui.grid.autoResize',
- 'ui.grid.expandable',
- 'ui.grid.selection',
- 'ui.grid.pinning',
- 'ui.bootstrap'])
- .config(function ($routeProvider, $locationProvider) {
- $locationProvider.hashPrefix('');
- $routeProvider
- .when('/', {
- templateUrl: 'Home',
- controller: 'homeController'
- })
- .when('/employee', {
- templateUrl: 'Employee',
- controller: 'employeeController'
- });
-
-
- });
Service
- app.service('employeeService', function ($http) {
-
- this.getEmployees = function () {
- var req = $http.get('api/EmployeeAPI/GetEmployee');
- return req;
- };
-
- this.addEmployee = function (saveData)
- {
- var req = $http.post('api/EmployeeAPI/AddEmployee', JSON.stringify(saveData),
- {
- headers: {
- 'Content-Type': 'application/json'
- }
- });
- return req;
- };
-
- this.updateEmployee = function (saveData)
- {
- var req = $http.post('api/EmployeeAPI/UpdateEmployee', JSON.stringify(saveData),
- {
- headers: {
- 'Content-Type': 'application/json'
- }
- });
- return req;
- };
-
- this.deleteEmployee = function (employeeID) {
- var req = $http.get('api/EmployeeAPI/DeleteEmployee', { params: { EmployeeID: employeeID } });
- return req;
- };
- });
Controllers:
employeeController
- app.controller("employeeController", function (
- $scope, $filter,
- employeeService, $window,
- $http, $log, $interval, $uibModal) {
- init();
-
- function init(){
- employeeService.getEmployees().then(function (result) {
- $scope.gridOptions.data = result.data;
- console.log($scope.Employees);
- }, function (error) {
- $window.alert('Oops! Something went wrong while fetching employee data.');
- });
- var paginationOptions = {
- pageNumber: 1,
- pageSize: 10,
- };
- $scope.gridOptions = {
- enableRowSelection: true,
- selectionRowHeaderWidth: 35,
- enableRowHeaderSelection: false,
- paginationPageSizes: [10, 20, 30, 40],
- paginationPageSize: 10,
- enableSorting: true,
- columnDefs: [
- { name: 'Edit', field: 'EmployeeID', width: '10%', enableColumnMenu: false, cellTemplate: '<button title="Edit" class="btn btn-xs btn-primary fa fa-edit" ng-click="grid.appScope.editEmployee(row)">Edit </button>', width: 50, pinnedLeft: false, enableHiding: false, exporterSuppressExport: true, enableSorting: false, enableFiltering: false },
- { name: 'First Name', field: 'FirstName', headerCellClass: 'tablesorter-header-inner', enableFiltering: true, enableCellEdit: true, },
- { name: 'Last Name', field: 'LastName', headerCellClass: 'tablesorter-header-inner', enableFiltering: true, enableCellEdit: true, },
- { name: 'City', field: 'City', headerCellClass: 'tablesorter-header-inner', enableFiltering: true, enableCellEdit: true, },
- { name: 'Region', field: 'Region', enableCellEdit: false, headerCellClass: 'tablesorter-header-inner', enableFiltering: true },
- { name: 'Postal Code', field: 'PostalCode', enableCellEdit: false, headerCellClass: 'tablesorter-header-inner', enableFiltering: true },
- { name: 'Country', field: 'Country', enableCellEdit: false, headerCellClass: 'tablesorter-header-inner', enableFiltering: true },
- { name: 'Notes', field: 'Notes', width: '20%', enableCellEdit: false, headerCellClass: 'tablesorter-header-inner', enableFiltering: true }
- ],
-
- enableGridMenu: true,
- enableSelectAll: true,
- exporterMenuPdf: false,
- enableFiltering: true,
- exporterCsvFilename: 'EmployeeList_' + $filter('date')(new Date(), 'MM/dd/yyyy') + '.csv',
- exporterCsvLinkElement: angular.element(document.querySelectorAll(".custom-csv-link-location")),
- onRegisterApi: function (gridApi) {
- $scope.gridApi = gridApi;
- },
-
- };
- }
-
- $scope.addEmployee = function()
- {
- var modalInstance = $uibModal.open({
-
- templateUrl: 'Template/add.html',
- controller: 'addEmployeeController',
-
-
-
- size: 'md',
- backdrop: 'static',
- keyboard: false,
-
- resolve: {
-
-
-
- row: function () { return null; }
- }
- }).closed.then(function () {
- $scope.RefreshGridData();
- $scope.showGrid = true;
- }, function () { }
- );
- };
-
- $scope.editEmployee = function(row)
- {
- var modalInstance = $uibModal.open({
-
- templateUrl: 'Template/edit.html',
- controller: 'editEmployeeController',
-
-
-
- size: 'md',
- backdrop: 'static',
- keyboard: false,
-
- resolve: {
-
-
- row: function () { return row.entity; }
- }
- }).closed.then(function () {
- $scope.RefreshGridData();
- $scope.showGrid = true;
- }, function () { }
- );
- }
-
- $scope.RefreshGridData = function()
- {
- employeeService.getEmployees().then(function (result) {
- $scope.gridOptions.data = result.data;
- console.log($scope.Employees);
- }, function (error) {
- $window.alert('Oops! Something went wrong while fetching employee data.');
- });
- }
-
- });
addEmployeeController
- app.controller("addEmployeeController", function ($scope,
- $filter,
- employeeService,
- $window,
- $http,
- $log,
- $interval,
- $uibModalInstance,
- $uibModal,
- row) {
- if(row == null)
- {
- $scope.title = "Add Employee";
- }
- else
- {
- $scope.title = "Edit Employee";
- $scope.rowData = angular.copy(row);
- }
-
- $scope.add = function()
- {
- if (confirm("Are you sure you want to save these changes?") === false) {
- return;
- }
- else {
- var saveData = {
- EmployeeID: $scope.rowData.EmployeeID,
- FirstName: $scope.rowData.FirstName,
- LastName: $scope.rowData.LastName,
- City: $scope.rowData.City,
- Region: $scope.rowData.Region,
- PostalCode: $scope.rowData.PostalCode,
- Country: $scope.rowData.Country,
- Notes: $scope.rowData.Notes
- };
- employeeService.addEmployee(saveData).then(function () {
- console.log("Successfullly Added.");
- $scope.showSuccessMessage = true;
- }, function (error) {
- $window.alert('Error occurred while adding employee');
- });
- }
- }
-
- $scope.close = function()
- {
- $uibModalInstance.dismiss('cancel');
- }
-
- $scope.cancel = function()
- {
- $uibModalInstance.dismiss('cancel');
- }
- });
editEmployeeController
- app.controller("editEmployeeController", function ($scope,
- $filter,
- employeeService,
- $window,
- $uibModalInstance,
- $http,
- $log,
- $interval,
- $uibModal,
- row) {
- if(row == null)
- {
- $scope.title = "Add Employee";
- }
- else
- {
- $scope.title = "Edit Employee";
- $scope.rowData = angular.copy(row);
- }
-
- $scope.save = function()
- {
- if (confirm("Are you sure you want to update these changes?") === false) {
- return;
- }
- else {
- var saveData = {
- EmployeeID: $scope.rowData.EmployeeID,
- FirstName: $scope.rowData.FirstName,
- LastName: $scope.rowData.LastName,
- City: $scope.rowData.City,
- Region: $scope.rowData.Region,
- PostalCode: $scope.rowData.PostalCode,
- Country: $scope.rowData.Country,
- Notes: $scope.rowData.Notes
- };
- employeeService.updateEmployee(saveData).then(function () {
- console.log("Successfullly Updated.");
- $scope.showSuccessMessage = true;
- $scope.ConfirmationMessage = "Employee has been update.";
- }, function (error) {
- $window.alert('Error occurred while updating employee details');
- });
- }
- }
-
- $scope.remove = function()
- {
- if (confirm("Are you sure you want to delete this employee?") === false) {
- return;
- }
- else {
- employeeService.deleteEmployee($scope.rowData.EmployeeID).then(function () {
- console.log("Successfullly Deleted.");
- $scope.showSuccessMessage = true;
- $scope.ConfirmationMessage = "Employee has been deleted.";
- }, function (error) {
- $window.alert('Error occurred while deleting employee.');
- });
- }
- }
-
- $scope.close = function()
- {
- $uibModalInstance.dismiss('cancel');
- }
-
- $scope.cancel = function()
- {
- $uibModalInstance.dismiss('cancel');
- }
- });
Index
- @{
- ViewBag.Title = "Index";
- Layout = "~/Views/Shared/_Layout.cshtml";
- }
- <h2>Employee</h2>
- <div ng-controller="employeeController">
- <div style="padding-left: 30px;">
- <button type="button" id="addRow" class="btn btn-success" ng-click="addEmployee()">Add New Employee</button>
- </div>
- <br />
- <div ui-grid="gridOptions"
- ui-grid-pagination
- ui-grid-selection
- ui-grid-exporter
- ui-grid-resize-columns
- ui-grid-auto-resize
- class="grid">
- </div>
- </div>
Edit.html
- <div>
- <div class="modal-header">
- <button type="button" class="close" ng-click="cancel()"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
- <h4 class="modal-title coloredText">{{ title }}</h4>
- </div>
- <div class="modal-body">
- <form name="serviceForm" class="form-horizontal">
- <div class="form-group">
- <label class="control-label col-sm-2">ID:</label>
- <div class="col-sm-10">
- {{ rowData.EmployeeID }}
- </div>
- </div>
- <div class="form-group">
- <label for="firstname" class="control-label col-sm-2">First Name:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.FirstName" />
- </div>
- </div>
- <div class="form-group">
- <label for="lastname" class="control-label col-sm-2">Last Name:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.LastName" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">City:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.City" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Region:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.Region" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Postal Code:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.PostalCode" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Country:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.Country" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Notes:</label>
- <div class="col-sm-10">
- <textarea class="form-control" type="text" rows="5" ng-model="rowData.Notes" />
- </div>
- </div>
- <div class="alert alert-success" ng-show="showSuccessMessage">
- <strong>Success!</strong>{{ ConfirmationMessage }}
- </div>
- </form>
- </div>
- <div class="modal-footer">
- <div class="row">
- <div class="col-lg-6 spaceTop pull-right">
- <button class="active" ng-click="save()">Save</button>
- <button class="btn-danger" ng-click="remove()">Delete</button>
- <button class="btn-warning" ng-click="close()">Cancel</button>
- </div>
- </div>
- </div>
- </div>
Add.html
- <div class="modal-header">
- <button type="button" class="close" ng-click="cancel()"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
- <h4 class="modal-title coloredText">{{ title }}</h4>
- </div>
- <form name="serviceForm" class="form-horizontal">
- <div class="form-group">
- <div class="col-sm-10">
- </div>
- </div>
- <div class="form-group">
- <label for="firstname" class="control-label col-sm-2">First Name:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.FirstName" />
- </div>
- </div>
- <div class="form-group">
- <label for="lastname" class="control-label col-sm-2">Last Name:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.LastName" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">City:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.City" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Region:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.Region" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Postal Code:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.PostalCode" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Country:</label>
- <div class="col-sm-10">
- <input class="form-control" type="text" ng-model="rowData.Country" />
- </div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-2">Notes:</label>
- <div class="col-sm-10">
- <textarea class="form-control" type="text" rows="5" ng-model="rowData.Notes" />
- </div>
- </div>
- <div class="alert alert-success" ng-show="showSuccessMessage">
- <strong>Success!</strong>Employee has been saved.
- </div>
- </form>
- <div class="modal-footer">
- <div class="row">
- <div class="col-lg-6 spaceTop pull-right">
- <button class="active" ng-click="add()">Add</button>
- <button class="btn-warning" ng-click="close()">Cancel</button>
- </div>
- </div>
- </div>
As everything is done, run the application.
![]()
Let’s add a new employee, hit add new employee button.
![]()
Now let’s add edit an existing employee, click on Edit button from list.
![]()
As you can see confirmation message appears after edit and delete and when you click the model dialog grid data refreshed with new changes.
![]()
Conclusion
In this article, we have seen how to implement CRUD functionality with model dialog and with Angular UI-Grid with Web API and Entity Framework in MVC. If you have any questions or comments, drop me a line in the comments section.