<!DOCTYPE html>
<html>
<head>
<link data-require="fontawesome@*" data-semver="4.1.0" rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/ng-grid/2.0.11/ng-grid.css" type="text/css" rel="stylesheet" />
<link href="style.css" type="text/css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-grid/2.0.11/ng-grid.debug.js" type="text/javascript"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="tableExpandCollapseApp">
<div ng-controller="tableExpandCollapseController">
<div class="headerPane">
<h1 class="header"> Description</h1>
Tables that supports expand (+) and collapse (-) rows.
<ul>
<li>Click
<span class="fa-stack fa-lg">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-plus fa-stack-1x fa-inverse"></i>
</span>
(of any row parenet row) to view it's details (child rows) if present.</li>
<li>Click <span class="fa-stack fa-lg">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-minus fa-stack-1x fa-inverse"></i>
</span>
(of any row parenet row) to hide it's details (child rows)</li>
</ul>
<hr />
</div>
<div class="left">
<h2 class="header">HTML table</h2>
<table>
<thead>
<tr>
<td></td>
<td>Name</td>
<td>Quantity</td>
<td>Type</td>
<td>Cost</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="si in selItems">
<td>
<div ng-if="si.Summary">
<!-- <button ng-click="toggleDisplay(si.Type)"> -->
<div ng-if="si.Summary == '+'">
<a href="" ng-click="toggleDisplay(si.Type)">
<i class="fa fa-plus"></i>
</a>
</div>
<div ng-if="si.Summary == '-'">
<a href="" ng-click="toggleDisplay(si.Type)">
<i class="fa fa-minus"></i>
</a>
</div>
<!-- </button> -->
</div>
</td>
<td>{{si.Name}}</td>
<td>{{si.Quantity}}</td>
<td>{{si.Type}}</td>
<td>{{si.Cost}}</td>
</tr>
</tbody>
</table>
<hr />
</div>
<div class="right">
<h2 class="header">ngGrid</h2>
<div ng-grid="gridOptions"></div>
<hr />
</div>
</div>
</body>
</html>
var app = angular.module('tableExpandCollapseApp', ['ngGrid']);
app.service('shoppingList', function($http, $q) {
var items;
return {
getShoppingList: function() {
if (angular.isUndefined(items)) {
items = {};
return $http.get('http://cdn.rawgit.com/abhijithda/jnaan/master/items.json').success(function(jsonData) {
items["Items"] = jsonData["Items"];
});
} else {
return $q.when(items);
}
}
};
});
app.controller('tableExpandCollapseController',
function($scope, shoppingList) {
$scope.displayItemDetails = {};
$scope.toggleDisplay = function(iType) {
console.log("Toggling display of " + iType + " from " + $scope.displayItemDetails[iType]);
$scope.displayItemDetails[iType] = $scope.displayItemDetails[iType] ? 0 : 1;
console.log(" to " + $scope.displayItemDetails[iType]);
console.log(" All display details value:");
console.log($scope.displayItemDetails);
$scope.selItems = $scope.updateTable();
console.log("In toggleDisplay()::selItems: ");
console.log($scope.selItems);
};
$scope.updateTable = function() {
var selItems = [];
for (var i in $scope.allItems) {
var iType = $scope.allItems[i]["Type"];
if (angular.isUndefined($scope.displayItemDetails[iType])) {
$scope.displayItemDetails[iType] = 0;
}
if (1 == $scope.displayItemDetails[iType]) {
$scope.allItems[i]["Summary"] = '-';
console.log("Expanding(" + $scope.allItems[i]["Summary"] + ") details of " + iType);
} else {
$scope.allItems[i]["Summary"] = '+';
console.log("Collapsing(" + $scope.allItems[i]["Summary"] + ") details of " + iType);
}
selItems.push($scope.allItems[i]);
console.log("Display details of " + iType + ": " + $scope.displayItemDetails[iType]);
if ($scope.displayItemDetails[iType]) {
console.log("Viewing details of " + iType);
for (var j in $scope.allItems[i]["Details"]) {
$scope.allItems[i]["Details"][j]["Summary"] = "";
selItems.push($scope.allItems[i]["Details"][j]);
}
}
}
console.log("In updateTable()::selItems: ");
console.log(selItems);
return selItems;
};
shoppingList.getShoppingList().then(function(result) {
console.log("Result: ");
console.log(result);
$scope.allItems = result.data.Items;
$scope.selItems = $scope.updateTable();
console.log("In then::selItems: ");
console.log($scope.selItems);
});
var summaryCellTemplate = "<div ng-if='row.getProperty(col.field)'>" +
"<button ng-click='toggleDisplay(row.entity.Type)'> {{row.getProperty(col.field)}} </button>" +
"</div>";
$scope.gridOptions = {
data: 'selItems',
columnDefs: [{
field: 'Summary',
displayName: '',
cellTemplate: summaryCellTemplate,
width: 30
}, {
field: 'Name',
displayName: 'Name',
}, {
field: 'Type',
displayName: 'Type',
}, {
field: 'Cost',
displayName: 'Cost',
}, {
field: 'Quantity',
displayName: 'Quantity',
}],
enableCellSelection: false,
enableColumnResize: true
};
});
* {
padding: 10;
margin: 10;
border: 10;
}
.header {
background-color: rgba(44, 163, 0, 0.4);
}
.headerPane {
clear: none;
float: left;
position: relative;
width: 100%;
height: 20%;
}
.left {
clear: none;
float: left;
position: relative;
width: 50%;
height: 80%;
}
.right {
clear: none;
float: left;
position: relative;
width: 50%;
height: 80%;
}
.ngViewport.ng-scope {
height: auto !important;
overflow-y: hidden;
}
.ngTopPanel.ng-scope, .ngHeaderContainer {
width: auto !important;
}
Table expand and collapse rows
# Description
Allow expand/collapse of rows of a table in order to view/hide details. When a row is expanded, new rows will show up the details of the expanded row.
# Example:
Below table that shows the overview:
|Name | Quantity | Type | Cost
---|-------|-----------|--------|------
[+](# expand)|Fruits | 5 | Fruit | 10
[+](# expand)|Vegetables | 2 | Vegetable | 5
[+](# expand)|Pulses | 2 | Pulse | 40
[+](# expand)|Drinks | 4 | Drink | 20
Below table that shows the details of Fruits item when '+' of the Fruits row is clicked.
|Name | Quantity | Type | Cost
---|-------|-----------|--------|------
[-](# collapse)|Fruits | 5 | Fruit | 10
|Banana | 2 | Fruit | 1
|Apple | 2 | Fruit | 4
|Pomogrande | 1 | Fruit | 5
[+](# expand)|Vegetables | 2 | Vegetable | 5
[+](# expand)|Pulses | 2 | Pulse | 40
[+](# expand)|Drinks | 4 | Drink | 20
{
"Items": [{
"Name": "Fruits",
"Type": "Fruit",
"Quantity": 5,
"Cost": 10,
"Details": [{
"Name": "Banana",
"Type": "Fruit",
"Quantity": 2,
"Cost": 1
}, {
"Name": "Apple",
"Type": "Fruit",
"Quantity": 2,
"Cost": 4
}, {
"Name": "Pomogrande",
"Type": "Fruit",
"Quantity": 1,
"Cost": 5
}]
}, {
"Name": "Vegetables",
"Type": "Vegetable",
"Quantity": 2,
"Cost": 5,
"Details": []
}, {
"Name": "Pulses",
"Type": "Pulse",
"Quantity": 2,
"Cost": 40,
"Details": []
}, {
"Name": "Drinks",
"Type": "Drink",
"Quantity": 4,
"Cost": 20,
"Details": [{
"Name": "Water",
"Type": "Drink",
"Quantity": 2,
"Cost": 1
}, {
"Name": "Coconut Water",
"Type": "Drink",
"Quantity": 2,
"Cost": 4
}, {
"Name": "Pomogrande Juice",
"Type": "Drink",
"Quantity": 1,
"Cost": 5
}]
}]
}