If you want to know how to get started with UI-Grid and how to set up a project in AngularJS and Web API, read the articles given below first.
Angular-UI-Grid has expandable feature which adds the sub grid feature to grid. You can load any data source when click on expand icon.
In this article, I am going to use NORTHWND database and Employee, Employee Territories tables. My feature grid will load all employees and when click on expand then employees territories will load in sub grid.
After creating all basic and adding mandatory script, let’s implement expandable feature on ui-grid. Thus, after adding data in Entity Model, create a Web API to get the data from Entity model.
Entity Model
Web API
Here, my Web API class code is given below.
Module
- var employeeapp = angular.module('employeeapp', ['ui.grid', 'ui.grid.pagination',
- 'ui.grid.selection', 'ui.grid.exporter',
- 'ui.grid.grouping', 'ui.grid.expandable']);
Service
-
- employeeapp.service("employeeservice", function ($http, $timeout) {
-
- this.GetEmployee = function () {
- var req = $http.get('api/employeeapi/get');
- return req;
- }
-
- this.GetTerritories = function (employeeId) {
- var req = $http.get('api/employeeapi/getterritoriesbyid?id=' + employeeId);
- return req;
- }
- });
Controller
-
- employeeapp.controller("employeegroupingcontroller", function ($scope, employeeservice, $filter, $window, $interval, uiGridGroupingConstants, $timeout) {
- GetEmployee();
- function GetEmployee() {
- employeeservice.GetEmployee().then(function (result) {
- $scope.Employees = result.data;
- console.log($scope.Employees);
- }, function (error) {
- $window.alert('Oops! Something went wrong while fetching genre data.');
- })
- }
-
- $scope.columnDefs = [
- { name: '', field: 'EmployeeID', enableColumnMenu: false },
- { name: 'photo', enableSorting: false, field: 'PhotoPath', cellTemplate: "<img width=\"50px\" ng-src=\"{{grid.getCellValue(row, col)}}\" lazy-src>", enableCellEdit: false, enableFiltering: false, enableGrouping:false },
- { name: 'First Name', field: 'FirstName', headerCellClass: 'tablesorter-header-inner', enableCellEdit: true, enableFiltering: true, enableGrouping:false },
- { name: 'Last Name', field: 'LastName', headerCellClass: 'tablesorter-header-inner', enableCellEdit: true, enableFiltering: true, enableGrouping:false },
- { name: 'Title', field: 'Title', headerCellClass: 'tablesorter-header-inner', enableCellEdit: true, enableFiltering: false, enableGrouping:false },
- { name: 'City', field: 'City', headerCellClass: 'tablesorter-header-inner', enableCellEdit: true, enableFiltering: true, enableGrouping:false },
- { name: 'Country', field: 'Country', headerCellClass: 'tablesorter-header-inner', enableCellEdit: true, enableFiltering: true, enableGrouping:false },
- { name: 'Notes', field: 'Notes', headerCellClass: 'tablesorter-header-inner', enableCellEdit: true, enableFiltering: false, enableGrouping:false },
- { name: 'Salary', field: 'Salary', headerCellClass: 'tablesorter-header-inner', enableCellEdit: true, enableFiltering: false, enableGrouping:true }
- ];
-
-
- $scope.gridOptions = {
-
- enableGridMenu: false,
- enableRowSelection: true,
- enableRowHeaderSelection: false,
- paginationPageSizes: [5, 10, 20, 30, 40],
- paginationPageSize: 10,
- enableSorting: true,
- exporterMenuPdf: false,
- enableFiltering: false,
- treeRowHeaderAlwaysVisible: false,
-
- exporterCsvFilename: 'Test_' + $filter('date')(new Date(), 'MM/dd/yyyy') + '.csv',
- exporterCsvLinkElement: angular.element(document.querySelectorAll(".custom-csv-link-location")),
-
- expandableRowTemplate: '<div ui-grid="row.entity.subGridOptions" style="height:140px;" ></div>',
-
-
- expandableRowScope: {
- subGridVariable: 'subGridScopeVariable'
- },
-
- onRegisterApi: function (gridApi) {
- $scope.gridApi = gridApi;
- gridApi.expandable.on.rowExpandedStateChanged($scope, function (row) {
- if (row.isExpanded) {
- row.entity.subGridOptions = {
- columnDefs: [
- { name: 'Employee Id', field:'EmployeeID'},
- { name: 'Territory Description', field:'TerritoryDescription'}
- ]};
- employeeservice.GetTerritories(row.entity.EmployeeID).then(function (data) {
- row.entity.subGridOptions.data = data.data;
- });
- }
- });
- },
-
- columnDefs: $scope.columnDefs,
-
- data: 'Employees'
- };
- });
To show the subgrid you need to provide following grid option:
- gridOptions - Options for configuring the expandable feature, these are available to be set using the ui-grid gridOptions
- publicApi - Public Api for expandable feature
Global
Now, add a few lines in Global.asax in Application_Start event.
- GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
- GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Now, add the mandatory packages given below, using NuGet Package Manager.
Bundling
Bundle the required styles and scripts.
Add the bundles given below in BundleConfig.cs
- bundles.Add(new ScriptBundle("~/bundles/uigrid").Include(
- "~/Scripts/ui-grid.min.js"));
- bundles.Add(new ScriptBundle("~/bundles/angular").Include(
- "~/Scripts/angular.min.js",
- "~/Angular/Controller/employeecontroller.js",
- "~/Angular/Controller/employeegroupingcontroller.js"));
- Render all the scripts and styles in _Loyout.cshtml
- @Styles.Render("~/Content/css")
- @Scripts.Render("~/bundles/modernizr")
- @Scripts.Render("~/bundles/jquery")
- @Scripts.Render("~/bundles/bootstrap")
- @Scripts.Render("~/bundles/angular")
- @Scripts.Render("~/bundles/uigrid")
- @RenderSection("scripts", required: false)
View
- @{
- ViewBag.Title = "Index";
- Layout = "~/Views/Shared/_Layout.cshtml";
- }
- <h2>Employee List</h2>
- <div ng-app="employeeapp" ng-controller="employeegroupingcontroller">
- <div ui-grid="gridOptions"
- class="grid"
- ui-grid-pagination
- ui-grid-selection
- ui-grid-auto-resize
- ng-cloak
- ui-grid-exporter
- ui-grid-expandable>
- </div>
- </div>
Output
In given screenshot as you can see first column has expandable icon. If you click on header expandable icon that will open or close all subgrids.
If you click on one icon that open a sub grid which has all territories for selected employee.
If you have more records then scroll bar should come in subgrid.
Conclusion
In this article, we have seen how to implement expandable in angular ui-grid with Web API with an Entity Framework in MVC. If you have any question or comments, drop me a line in the comments section.