var app = angular.module("app", []);
app.controller("MainController", function($scope) {
$scope.samplePositions = [
{"#": "1", "Unique ID": "100130", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 1", "Status": "Available"},
{"#": "2", "Unique ID": "100131", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 2", "Status": "Available"},
{"#": "3", "Unique ID": "100132", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 3", "Status": "Available"},
{"#": "4", "Unique ID": "100133", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 4", "Status": "Available"},
{"#": "5", "Unique ID": "100134", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 5", "Status": "Checked Out"},
{"#": "6", "Unique ID": "100135", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 6", "Status": "Checked Out"},
{"#": "7", "Unique ID": "100136", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 7", "Status": "Checked Out"},
{"#": "8", "Unique ID": "100137", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 8", "Status": "Checked Out"},
{"#": "9", "Unique ID": "100138", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 1 - Box 1 - Position 1", "Status": "Available"},
{"#": "10", "Unique ID": "100139", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 2 - Box 1 - Position 1", "Status": "Available"},
{"#": "11", "Unique ID": "100140", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 2 - Box 1 - Position 2", "Status": "Available"},
{"#": "12", "Unique ID": "100141", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 2 - Box 1 - Position 3", "Status": "Lost"},
{"#": "13", "Unique ID": "100142", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 2 - Box 1 - Position 4", "Status": "Lost"},
{"#": "14", "Unique ID": "100143", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 3 - Box 1 - Position 1", "Status": "Available"},
{"#": "15", "Unique ID": "100144", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 3 - Box 1 - Position 2", "Status": "Available"},
{"#": "16", "Unique ID": "100145", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 4 - Box 1 - Position 1", "Status": "Checked Out"},
{"#": "17", "Unique ID": "100146", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 4 - Box 1 - Position 2", "Status": "Available"},
{"#": "18", "Unique ID": "100147", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 4 - Box 1 - Position 3", "Status": "Available"},
{"#": "19", "Unique ID": "100148", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 4 - Box 1 - Position 4", "Status": "Checked Out"},
{"#": "20", "Unique ID": "100149", "Name": "Book", "Section": "Paraguay", "Position": "Shelf 1 - Rack 5 - Box 1 - Position 1", "Status": "Available"}
]
// Dynamically get the entry headers to use with displaying the nested data via header-key lookups
// Assumes all lines contain same key-text data
$scope.samplePositionsHeaderKeys = []; // Contains only the key-data, not the values
for (var key in $scope.samplePositions[0]) {
if ($scope.samplePositions[0].hasOwnProperty(key)) {
$scope.samplePositionsHeaderKeys.push(key);
}
}
/**
* Determine if the input value is a number or not.
* @param n The input value to be checked for numeric status.
* @returns true if parameter is numeric, or false otherwise.
*
* This method uses the following evaluations to determine if input is a numeric:
*
* (5); // true
* ('123'); // true
* ('123abc'); // false
* ('q345'); // false
* (null); // false
* (""); // false
* ([]); // false
* (' '); // false
* (true); // false
* (false); // false
* (undefined); // false
* (new String('')); // false
*
* @author C.D. (modified by)
* @original https://mcmap.net/q/73284/-check-whether-variable-is-number-or-string-in-javascript
*
*/
function isNumeric(n) {
if (!isNaN(parseFloat(n)) && !isNaN(n - 0) && n !== null && n !== "") {
return true;
}
return false;
}
/**
* Column Sort Method (generic). Sort based on target column header or reverse sort if already selected on that.
* @param dataSource The array of JSON data to be sorted
* @param headers The array of JSON object-keys (table column headers) to be referenced
* @param index The target JSON object-key to sort the table columns based upon
*
* @author C.D.
*/
$scope.lastSortIndex = 0;
$scope.toggleSort = function (dataSource, headers, index) {
if ($scope.lastSortIndex === index) {
dataSource.reverse();
}
else {
var key = headers[index];
if (key === "#" || isNumeric(dataSource[key])) { // Compare as numeric or on '#' sign
dataSource.sort((a, b) => parseFloat(a[key]) - parseFloat(b[key]));
}
else // Compare as Strings
{
try { // Attempt to sort as Strings
dataSource.sort((a, b) => a[key].localeCompare(b[key]));
} catch (error) {
if (error.name === 'TypeError') { // Catch type error, actually sort as Numeric
dataSource.sort((a, b) => parseFloat(a[key]) - parseFloat(b[key]));
}
}
}
$scope.lastSortIndex = index;
}
}
});
<html ng-app="app">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>AngularJS - Hello World</title>
<script data-require="jquery@*" data-semver="3.1.1" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script data-require="[email protected]" data-semver="1.3.13" src="https://code.angularjs.org/1.3.13/angular.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainController">
<div class="container">
<table class="table table-hover table-sm">
<thead>
<tr>
<th ng-repeat="header in samplePositionsHeaderKeys">
<a ng-click="toggleSort(samplePositions, samplePositionsHeaderKeys, $index)">{{ header }}</a>
</th>
</tr>
</thead>
<tbody>
<!-- Data is nested, so double-repeat to extract and display -->
<tr ng-repeat="row in samplePositions" >
<td ng-repeat="key in samplePositionsHeaderKeys">
{{row[key]}}
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>