使用AngularJs实现可排序的表格列

11
我是一位有用的助手,可以为您进行翻译。以下是需要翻译的内容:

我正在尝试对从JSON源填充的数据表进行排序。 我的代码如下:

HTML:

<div ng-app="myApp">
    <div ng-controller="PurchasesCtrl">
        <table cellspacing="0">
            <tr class="first">
                <th class="first" ng:click="changeSorting(purchases.date)">Date</th>
                <th ng:click="changeSorting(purchases.text)">Description</th>
                <th ng:click="changeSorting(purchases.price)">Amount</th>
                <th ng:click="changeSorting(purchases.availability)">Status</th>
            </tr>
            <tr ng-repeat="purchase in purchases.data">
                <td class="first">{{purchase.date}}</td>
                <td>{{purchase.text}}</td>
                <td>{{purchase.price}}</td>
                <td>{{purchase.availability}}</td>
            </tr>
        </table>
    </div>
</div>

JS:

var myApp = angular.module("myApp",[]);

myApp.factory("Purchases", function(){
    var Purchases = {};

    Purchases.data = [
        {
            date: "10/05/2012",
            text: "1 Lorem ipsum dolor sit amet ipsum dolor",
            price: "£123.45",
            availability: "1 Available until 10th Dec 2013"
        },
        {
            date: "24/05/2012",
            text: "2 Lorem ipsum dolor sit amet ipsum dolor",
            price: "£234.56",
            availability: "2 Available until 10th Dec 2013"
        },
        {
            date: "20/05/2012",
            text: "3 Lorem ipsum dolor sit amet ipsum dolor",
            price: "£345.67",
            availability: "3 Available until 10th Dec 2013"
        }
    ];
    return Purchases;
});

function PurchasesCtrl($scope, Purchases){
    $scope.purchases = Purchases;

    $scope.changeSorting = function(column) {
        var sort = $scope.sort;

        if (sort.column == column) {
            sort.descending = !sort.descending;
        } else {
            sort.column = column;
            sort.descending = false;
        }
    };
}

Fiddle: http://jsfiddle.net/7czsM/1/

您可以看到,我试图向表头添加一个点击函数来调用一个排序数据的函数,但它不起作用。

我看到了一个类似的例子,它确实起作用,这里是链接:http://jsfiddle.net/vojtajina/js64b/14/,但当我尝试将同样的方法应用到我的情况时,它很快就会崩溃;例如,我尝试通过在JSON中以编程方式添加表头来添加以下内容:

var Purchases = {};

Purchases.head = [
        {
            date: "Date",
            text: "Text column",
            price: "Price column",
            availability: "Availability column"
        }

    Purchases.data = [
        {
            date: "10/05/2012",
            text: "1 Lorem ipsum dolor sit amet ipsum dolor",
            price: "£123.45",
            availability: "1 Available until 10th Dec 2013"
        },

这只是防止任何东西工作,但我认为可以将多个数据集添加到Angular变量中?

我完全是Angular的新手,所以我真的被卡住了。任何指针都将不胜感激,谢谢。


1
你忘记了取 $scope.sort 函数。 - zs2020
抱歉,我不明白您的意思? - Dan
5个回答

27

更新的 jsfiddle: http://jsfiddle.net/gweur/

sza 是对的,您确实忘记了 $scope.sort 对象,但在 ng-repeat 中也缺少 orderBy 过滤器。

|orderBy:sort.column:sort.descending

另外,您需要明确地将列名传递给changeSorting()函数,例如

ng-click="changeSorting('text')"  

我不确定你是否有其他处理这件事情的方式。

最后,ng-click是你正在使用的AngularJS版本的正确语法。


8

另一个非常好的制作可排序表格的例子:

http://jsfiddle.net/vojtajina/js64b/14/

<th ng:repeat="(i,th) in head" ng:class="selectedCls(i)" ng:click="changeSorting(i)">{{th}}</th>

scope.changeSorting = function(column) {
    var sort = scope.sort;
    if (sort.column == column) {
        sort.descending = !sort.descending;
    } else {
        sort.column = column;
        sort.descending = false;
    }
};

5

这是我的解决方案。我还将整个内容封装为一个指令。唯一的依赖项是UI.Bootstrap.pagination,它在分页方面做得很好。

这里是plunker

这里是GitHub源代码。


你的排序有点混乱。点击名称列,你会看到:“name 1, name 10, name 11, name 12”等等(而应该是“name 1, name 2, name 3, ...”) - darksoulsong
它基于字符串。你可以创建自己的排序方法来替换它。这个想法基本上是一样的。 - maxisam

0

0

我认为你的AngularJS样板代码中,特别是设置控制器和工厂的部分,可能存在语法错误。

这里有一个例子,展示了你的数据如何在表格列排序方法上进行扩展。由于AngularJS擅长处理JavaScript数据结构以在HTML中显示,因此您可以在内存中重新排列JavaScript数组,AngularJS会自动检测到更改。这个例子允许点击表头,触发基于该列数据类型的排序。如果已经按该列排序,则会反向排序该列。类型检测通过isNumeric()函数完成,并进行了两个微小的调整:

  1. 在toggleSort方法中添加了对'#'符号作为标题输入并将其作为数字排序的检查。如果用户愿意,可以轻松删除此功能。
  2. 当toggleSort尝试按字母顺序排序时,如果捕获到TypeError,则切换到数字排序。

var myApp = angular.module("myApp", []);

myApp.factory("Purchases", function() {
  var Purchases = {};

  Purchases.data = [{
    date: "10/05/2012",
    text: "1 Lorem ipsum dolor sit amet ipsum dolor",
    price: "£123.45",
    availability: "1 Available until 10th Dec 2013"
  }, {
    date: "24/05/2012",
    text: "2 Lorem ipsum dolor sit amet ipsum dolor",
    price: "£234.56",
    availability: "2 Available until 10th Dec 2013"
  }, {
    date: "20/05/2012",
    text: "3 Lorem ipsum dolor sit amet ipsum dolor",
    price: "£345.67",
    availability: "3 Available until 10th Dec 2013"
  }];
  return Purchases;
});

myApp.controller("PurchasesCtrl", function($scope, Purchases) {
  $scope.purchases = Purchases.data;

  // 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.purchasesHeaderKeys = []; // Contains only the key-data, not the values
  for (var key in $scope.purchases[0]) {
    if ($scope.purchases[0].hasOwnProperty(key)) {
      $scope.purchasesHeaderKeys.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://dev59.com/Q3M_5IYBdhLWcg3wn0hO#1421988
   * 
   */
  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.changeSorting = 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;
      $scope.reverseSorted = false;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.13/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<html ng-app="myApp">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>AngularJS - Hello World</title>


  <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="PurchasesCtrl">
  <div class="container">
    <table class="table table-hover table-sm">
    <thead>
     <tr>
      <th ng-repeat="header in purchasesHeaderKeys">
       <a ng-click="changeSorting(purchases, purchasesHeaderKeys, $index)">{{ header }}</a>
      </th>
     </tr>
    </thead>
  
    <tbody>
     <!-- Data is nested, so double-repeat to extract and display -->
     <tr ng-repeat="row in purchases" >
      <td ng-repeat="key in purchasesHeaderKeys">
       {{row[key]}}
      </td>
     </tr>
    </tbody>
   </table>
  </div>
</body>

</html>

我已经准备好了一个工作的Plunker示例来演示。只需单击标题,它们将对内存中的数组进行排序,AngularJS将捕捉到这些更改并刷新DOM的那一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接