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.