9

$scope.recordsHTMLテーブルがあり、テーブルヘッダー(Ctrlキー)をクリックしてレコード(Ctrlキー)を並べ替えたいのですが$scope.headers

なぜそれが機能するのか誰かが説明できますか?

<th>
    <a ng-click="sortColumn=headers[0];reverse=!reverse">{{ headers[0] }}</a>
</th>
<th>
    <a ng-click="sortColumn=headers[1];reverse=!reverse">{{ headers[1] }}</a>
</th>

そして、それはしません:

<th ng-repeat="header in headers">
    <a ng-click="sortColumn=headers[$index];reverse=!reverse">{{ headers[$index] }}</a>
</th>

レコードのコードは次のとおりです。

<tr ng-repeat="arr in records | orderBy:sortColumn:reverse">
    <td ng-repeat="val in arr" ng-bind-html-unsafe="arr[headers[$index]]</td>
</tr>

テーブルに58の列があるので、テーブルヘッダーをループする方がはるかに良いでしょう...

4

3 に答える 3

12

Davidが示唆したように、これはおそらくスコープに関連しています。ngRepeatは新しいスコープを作成するため、各列ヘッダーの独自の子スコープにとをngClick設定します。sortColumnreverse

同じスコープ内の値を変更していることを確認する1つの方法は、スコープ上に関数を作成し、それをngClickで呼び出してインデックスを渡すことです。

$scope.toggleSort = function(index) {
    if($scope.sortColumn === $scope.headers[index]){
        $scope.reverse = !$scope.reverse;
    }                    
    $scope.sortColumn = $scope.headers[index];
}

これをマークアップとして:

<th ng-repeat="header in headers">
    <a ng-click="toggleSort($index)">{{ headers[$index] }}</a>
</th>

これが例のあるフィドルです。


別のオプションは、次のような非プリミティブ型にバインドすることです(子スコープは同じオブジェクトにアクセスします)。

$scope.columnSort = { sortColumn: 'col1', reverse: false };

これをマークアップとして:

<th ng-repeat="header in headers">
    <a ng-click="columnSort.sortColumn=headers[$index];columnSort.reverse=!columnSort.reverse">{{ headers[$index] }}</a>
</th>

これが例のあるフィドルです。

于 2012-10-05T15:21:37.603 に答える
3

Gloopyの答えを拡張し、さらに別のオプションは、プリミティブ型のng-repeatで親のプロパティを変更することです。

<a ng-click="$parent.sortColumn=headers[$index];$parent.reverse=!$parent.reverse">{{ headers[$index] }}

これがフィドルです。

ただし、$ parentはスコープの文書化されたプロパティではないため、これは多少のハックであることに注意してください。自己責任で使用してください。

プリミティブである親スコープのプロパティを変更する必要があることが非常に多いため、AngularJSに、ng-repeat、ng-switchなどによって作成されるこれらの「内部スコープ」を処理するためのより良い方法があればいいのにと思います。

スコープの継承に関するGloopyの洞察に満ちたコメントも参照してください。これは、プリミティブと非プリミティブに関連しているためです

于 2012-10-05T16:02:41.727 に答える
0

レコードにどのような種類のデータが含まれているかわからないため、サンプルではJSON値の配列を使用しました。Angularを使用してJavascript用にいくつかの異なる並べ替えプラグインを試しましたが、何も機能しませんでした。長い目で見れば、必ずしもこれらの追加機能は必要ないことがわかりました。

AngularJSはHTMLで表示するためのjavascriptデータ構造の処理に優れているため、メモリ内のjavascript-arrayを再配置するだけで、AngularJSが変更を取得します。この例では、テーブルのヘッダーをクリックすると、その列のデータ型に基づいて並べ替えがトリガーされます。その列ですでにソートされている場合は、列を逆ソートします。型の検出は、提示されたisNumeric()関数と、2つの小さな調整によって行われます。

  1. '#'記号をヘッダーとして入力し、toggleSortメソッドで数値としてソートする場合のチェックを追加しました。これは、必要に応じてユーザーが簡単に削除できます。
  2. toggleSortがアルファベット順に並べ替えようとすると、TypeErrorが検出されると、数値の並べ替えに切り替わります。

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;
			}
		}

});
<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/jquery@3.1.1/dist/jquery.min.js"></script>
  <script data-require="angular.js@1.3.13" 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>

実例となるプランカーの例をまとめました。ヘッダーをクリックするだけで、メモリ内の配列が並べ替えられ、AngularJSが変更を取得して、DOMのその部分を更新します。

于 2019-10-04T01:23:44.143 に答える