Introduction
While working with SPA (Single Page Application) using AngularJS in my project, I needed bulk upload to be implemented. I was stuck for some time and finally achieved this. So I thought it might be helpful for some others who have to implement bulk upload in their apps.
In this demo, I have used Visual Studio 2012, .NET Framework 4.5, AngularJs, Bootstrap and .mdf files for the database operations. I have provided all the necessary screenshots and source code to download.
Demo Overview
This demo is small medical bill application, where a user can upload multiple bills (not physical files) to the server in one go.
Important Things for Bulk Upload
- The way you define your model in AngularJS is very important to pass to server side.
- AngularJS model should match with model at the server side in order to pass data.
- Rest is up to you how to do bulk upload.
Creating Project in Visual Studio
Open Visual Studio 2012 and create a project with MVC4 template and I have named the project BulkInsert_Angularjs
, but you can name it anything you want.
Adding jQuery and AngularJS: The figure below shows I installed Bootstrap, AngularJS and Angular routing from NuGet packages. And I have also added a JavaScript file and named it as myApp
for later use.
Now, add these installed files to your MVC project. Go To -> App_Start -> BundleConfig. Add the below lines as I have shown in the red rectangle in the below figure:
Now, you have to make sure these files are added in your Master page (_Layout.cshtml) which is located in the Views -> Shared folder of the application. I always put my jQuery or required files inside the head
tag of my project to make it accessible to your entire application as shown in the below image.
So, now we have added jQuery, Angular, Angular routing, Bootstrap CSS and bootstrap.js files in our layout page and we need to make sure they are rendered on our browser properly without any errors. To double check, run the application in Chrome browser and press F12 to open browser tools. Check all the files are loaded by clicking on Sources tab and check that there are no errors on console tab. The below figure confirms all files are loaded properly with no errors in console tab.
Setting Up Database
I will add a .mdf file for the database operations and name it BulkDemo.mdf. I have created a table name called BillsClaim
. Below is the script of the table.
var app = angular.module('myApp', ['AngularDemo.HomeController'])
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: '/Home/Display',
controller: 'homeCtrl',
});
$routeProvider.when('/BulkInsert', {
templateUrl: '/Home/BulkInsert',
controller: 'homeCtrl',
});
$routeProvider.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(false).hashPrefix('!');
}]);
angular.module('AngularDemo.HomeController', ['ngRoute'])
.controller('homeCtrl', function ($scope, $http) {
$scope.TableLength = '';
$scope.MaxTableLength = 10;
$scope.ReceiptList = '';
$http.get('/Home/GetClaimsList').success(function (data) {
$scope.ReceiptList = data;
});
$scope.NewBill =
{
SingleNewBill: [
{
BillNum: '',
BillAmt: '',
Relationship: ''
}
]
};
$scope.ShowRow = function () {
var InputIdNo = $scope.NewBill.SingleNewBill.length + 1;
if ($scope.MaxTableLength >= InputIdNo) {
$scope.NewBill.SingleNewBill.push({ 'id': 'choice' + InputIdNo });
}
else {
alert("You cannot add more than 10 bills in one go");
}
};
$scope.CancelRow = function (Index) {
$scope.NewBill.SingleNewBill.splice(Index, 1);
};
$scope.AddNew = function (tblName) {
if ($scope.NewBill.SingleNewBill.length > 0) {
$.ajax({
url: '/Home/BulkSave',
type: 'POST',
dataType: 'json',
contentType: 'application/json',
traditional: true,
data: JSON.stringify({ billsClaimModel: $scope.NewBill.SingleNewBill }),
success: function (data) {
alert("Your Medical Bills have been added");
$("#tblName").remove();
$scope.NewBill = "";
}
});
}
else {
alert("Please add bill and then save");
}
};
});
Angular Code Explanation
Note: The angular.module
is a global place for creating, registering and retrieving Angular modules. All modules that should be available to an application must be registered using this mechanism. (https://docs.angularjs.org/api/ng/function/angular.module).
The 1st parameter is the name of your Angular app. For our demo, it is named as ‘myApp
’.
The 2nd parameter is an array of dependencies. We have only one dependency currently that is 'AngularDemo.HomeController
'.
ng-app
directive: Once you name your AngularJS, you have to use in your HTML page depending up on your requirements. For this demo, I have used ng-app
in _Layout
page in the HTML tag as shown below.
Client-side Routing
So we have defined the name of our AngularJS app and mentioned the array of dependencies. Now let’s create routing at the client side. For this, I have created two routes as below with templateUrl
and controller.
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: '/Home/Display',
controller: 'homeCtrl',
});
$routeProvider.when('/BulkInsert', {
templateUrl: '/Home/BulkInsert',
controller: 'homeCtrl',
});
$routeProvider.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(false).hashPrefix('!');
}]);
Whenever AngularJS finds the URL which was mentioned in routing, it goes to the corresponding AngularJS controller where we have to create models and Ajax calls to server. Below is the controller code.
$http.get('/Home/GetClaimsList').success(function (data)
will get all the rows from server and $scope.AddNew
function will pass list model to the server for bulkupload.
$scope
is responsible for setting model properties and functions/behavior of a particular controller.
angular.module('AngularDemo.HomeController', ['ngRoute'])
.controller('homeCtrl', function ($scope, $http) {
$scope.TableLength = '';
$scope.MaxTableLength = 10;
$scope.ReceiptList = '';
$http.get('/Home/GetClaimsList').success(function (data) {
$scope.ReceiptList = data;
});
$scope.NewBill =
{
SingleNewBill: [
{
BillNum: '',
BillAmt: '',
Relationship: ''
}
]
};
$scope.ShowRow = function () {
var InputIdNo = $scope.NewBill.SingleNewBill.length + 1;
if ($scope.MaxTableLength >= InputIdNo) {
$scope.NewBill.SingleNewBill.push({ 'id': 'choice' + InputIdNo });
}
else {
alert("You cannot add more than 10 bills in one go");
}
};
$scope.CancelRow = function (Index) {
$scope.NewBill.SingleNewBill.splice(Index, 1);
};
$scope.AddNew = function (tblName) {
if ($scope.NewBill.SingleNewBill.length > 0) {
$.ajax({
url: '/Home/BulkSave',
type: 'POST',
dataType: 'json',
contentType: 'application/json',
traditional: true,
data: JSON.stringify({ billsClaimModel: $scope.NewBill.SingleNewBill }),
success: function (data) {
alert("Your Medical Bills have been added");
$("#tblName").remove();
$scope.NewBill = "";
}
});
}
else {
alert("Please add bill and then save");
}
};
});
We have a SingleNewBill
object, with an array of columns, which is nested in NewBill
. When we pass this AngularJS model to server side controller action, it should be the list of a model. Otherwise, the model will be null
at server side.
Output Screens
Bulk Insert Tab
When user clicks on Bulk Insert Tab, the below screen will be displayed.
When user clicks on Add Bill, new table row is created with two text boxes and dropdown list controls and they can add up to 10 rows max, see the below screen shot.
Once you click on save button, the values are passed to controller action as shown in below screen shot. For bulk upload, I have used SqlBulkCopy
concept of .NET.
Database
All the values that are entered in UI are stored in the database. Below is the screen shot.
Home Tab
Once user clicks on Home Tab, the below screen will be displayed with data.
HTML Code Explanation
BulkInsert View
data-ng-repeat
is for loop of AngularJS. We are getting each array values and storing them in NewBill
object and passing it to controller action.
Home View
On clicking on Home Tab, we are getting all the results from server and storing in AngularJS array ReceiptList
. In the view, we are looping through the array with help of ng-repeat
directive of AngularJS.