I am new to Angular 1.6 and UI-grid, so I am struggling with something simple. I want to have one UI-grid defined in my main controller that gets redefined and re-used with data from different Angular controllers. More specifically, I would like to have multiple .CSHTML grid templates using a single grid definition in the main Angular controller. I would like to fill the grid data array from different Angular controllers, with different data and different column definitions. There will only ever be one active grid at a time.
Using a separate grid definition for each controller works, but I may eventually have 20 grids; so I don't want that much repeatable bloat in my main Angular controller. The only parts of the grid definition that change are the column definitions, and the data. A simplified project layout is below to help the discussion.
In my main Angular controller, I have a UI-grid definition that I want to re-use from multiple Angular controllers in different files. The grid definition is below:
//MainController in app.js
(function () {
'use strict';
angular.module('CRNApp', ['ui.bootstrap', 'ui.grid', 'ui.grid.autoResize', 'ui.grid.emptyBaseLayer', 'ui.grid.selection']);
MainController.$inject = ['$scope', '$http', '$uibModal', '$log','uiGridConstants'];
angular.module('CRNApp')
.controller('MainController', MainController);
$scope.policyList = { //grid options and data for policy data
rowHeight: 40,
enableFiltering: true,
enableRowSelection: true,
enableRowHeaderSelection: false,
data: 'policyData',
columnDefs: [ //the column defs will be different for each different controller
{ name: 'PolicyId'},
{ name: 'PolicyState'},
{ name: 'AgentName' },
{ name: 'InforcePremium' },
{ name: 'LOB'}
]
};
$scope.policyData = []; //stores policy array returned from MVC controller to UI
$scope.policySelected = 'false'; //tracks if a row is selected. Allows row-depenendent nav buttons to be enabled on bav bar
$scope.mySelectedPolicy = {};
//grid options for processor grid
$scope.policyList.multiSelect = false;
$scope.policyList.modifierKeysToMultiSelect = false;
$scope.policyList.noUnselect = false;
$scope.policyList.onRegisterApi = function (policyApi) {
$scope.policyApi = policyApi;
$scope.policyApi.selection.on.rowSelectionChanged($scope, function (row) {
if (row.isSelected) {
$scope.policySelected = 'true';
$scope.mySelectedPolicy = row.entity; //copy selected row so that we can access it from processor controller
}
else
$scope.policySelected = 'false';
});
};
//this function recalculates the height of the visible grid after the row count changes
$scope.getPolicyTableHeight = function () {
var rowHeight = 30; // your row height
var headerHeight = 30; // your header height
return {
height: ($scope.policyList.data.length * rowHeight + headerHeight) + "px"
};
};
}());
In the main _Layout.cshtml, there is a button on a navigation bar that is bound to a function in a separate Angular controller called "PolicyController". The name of the function is called "loadPoliciesGrid()". This function fills the policyData array in the policyList grid definition with data (see main controller above). I will have multiple buttons on the page that call a similar function in different controllers. For example, I will have a Processor button that calls a "LoadProcessors()" function in a ProcessorController Angular file. The "LoadProcessors()" function would re-use the same grid definition in the main controller, but the column defs and grid array would be different.
<input style="margin-top: 8px !important; margin-bottom: 8px !important; margin-left: 8px !important;" type="submit" value="Get Records" ng-controller="PolicyController" ng-click="loadPoliciesGrid()" class="btn btn-default btn-sm">
The function in the "PolicyController" to load the grid data is below. There will be other Angular controllers that call their own data and the grid definition in the main Controller should somehow have the appropriate column defs:
//PolicyController in policy.js
(function () {
angular.module('CRNApp');
PolicyController.$inject = ['$scope', '$http', '$uibModal', '$log'];
angular.module('CRNApp')
.controller('PolicyController', PolicyController);
function PolicyController($scope, $http, $uibModal, $log) {
$scope.loadPoliciesGrid = function () {
$scope.$parent.loading = true;
$http.get("/api/Policy")
.then(function (responsePol) {
$scope.$parent.policyData = responsePol.data;
$scope.$parent.showGrid = 'policies';
$scope.$parent.loading = false;
})
.catch(function (error) {
console.log(error);
});
};
};
}());
The grid template is bound to the policy controller in the Index.cshtml page, which gets loaded as a child page in the main _Layout.cshtml page. Each one of these templates should bind their data to the same UI-grid.:
@*Index.cshtml. Each template is bound to a different Angular controller*@
@{ViewBag.Title = "ICS Portal - Home Page";}
<div ng-include="'templates/policiesGrid.cshtml'" ng-controller="PolicyController"></div>
<div ng-include="'templates/processorGrid.cshtml'" ng-controller="ProcessorController"></div>
<div ng-include="'templates/usersGrid.cshtml'" ng-controller="UserController"></div>
The grid markup container is defined in a separate template file, called policiesgrid.cshtml. Each grid markup template is in a separate file but shoudl reference the same UI-grid definition:
<div style="margin-left: auto; margin-right: auto;">
<div ui-if="policyList.data.length>0" ng-style="getPolicyTableHeight()"
ui-grid-auto-resize ui-grid-empty-base-layer ui-grid-selection id="policyGrid"
ui-grid="policyList" class="processorGrid" ng-show="showGrid == 'policies'"
style="margin-left: auto; margin-right: auto;">
</div>
</div>