Angularjs table sort with ng-repeat

后端 未结 3 735
难免孤独
难免孤独 2020-12-30 10:11

I have an HTML table and want to sort my records ($scope.records in ctrl) by clicking on table headers ($scope.headers in ctrl),

Can anyone

3条回答
  •  自闭症患者
    2020-12-30 10:33

    I don't know what sort of data is in your records, so for my sample I just used an array of JSON values. I have tried several different sorting plugins for my Javascript with Angular and nothing worked. In the long run I have discovered you don't necessarily need those extras.

    Since AngularJS is good at processing javascript data-structures for displaying in HTML, you can just rearrange the javascript-arrays in memory, and AngularJS picks up on the changes. This example allows clicking the headers of the table, which will trigger a sorting based on that columns data type. If it is already sorted on that column, it will reverse-sort the column. The type detection is done through the presented isNumeric() function, and one two-tiny tweaks:

    1. Added checks if inputting on the '#' symbol as a header and sorts as a number in the toggleSort method. This can easily be removed by users if preferred.
    2. When toggleSort attempts to sort alphabetically, if it catches a TypeError it then switches to sorting on numbers.

    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://stackoverflow.com/a/1421988/10930451
    		 * 
    		 */
    		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;
    			}
    		}
    
    });
    
    
    
      
      AngularJS - Hello World
      
      
      
      
    
      
      
    
    
    
      
    {{ header }}
    {{row[key]}}

    I have put together a working Plunker example to demonstrate. Just click on the headers and they will sort the array in memory, where AngularJS will pick up on the changes and refresh that portion of the DOM.

提交回复
热议问题