wake-up-neo.com

Sortierbare Tabellenspalten mit AngularJs

Ich versuche, eine Datentabelle zu sortieren, die aus einer JSON-Quelle gefüllt wird. Der Code, den ich habe, lautet wie folgt:

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

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

Wie Sie sehen, habe ich versucht, den Tabellenüberschriften eine Klickfunktion hinzuzufügen, um eine Funktion aufzurufen, die die Daten sortiert, aber sie funktioniert nicht. 

Ich habe ein Beispiel für diese Art von Dingen gesehen, die funktioniert, hier: http://jsfiddle.net/vojtajina/js64b/14/ , aber wenn ich versuche, dasselbe auf mein Szenario anzuwenden es bricht sehr schnell ab; Ich habe beispielsweise versucht, die Tabellenüberschriften in JSON programmatisch hinzuzufügen, indem Sie Folgendes hinzufügen:

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"
        },

Dies verhindert lediglich, dass irgendetwas funktioniert, aber ich dachte, es wäre möglich, einer Angular -Variable mehrere Datensätze hinzuzufügen.

Ich bin ein absoluter Neuling in Angular, also bleibe ich bei diesem Thema. Alle Hinweise wären dankbar.

9
Dan

Jsfiddle aktualisiert: http://jsfiddle.net/gweur/

sza hat recht, Sie haben das $ scope.sort -Objekt vergessen, aber Sie haben auch den orderBy-Filter in Ihrem ng-repeat

|orderBy:sort.column:sort.descending

Außerdem müssen Sie den Spaltennamen explizit an die Funktion changeSorting () übergeben, z 

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

nicht sicher, ob es einen anderen Weg gibt, wie Sie damit umgehen können. 

Schließlich ist ng-click die richtige Syntax für die von Ihnen verwendete Version von AngularJS. 

25
kmdsax

Ein weiteres sehr gutes Beispiel, um den Tisch sortierbar zu machen

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

Hier ist meine Lösung. Ich wickle das Ganze auch in eine Direktive ein. Die einzige Abhängigkeit ist UI.Bootstrap.pagination, die beim Paginieren hervorragende Arbeit geleistet hat.

Hier ist der Plunker

Hier ist der github-Quellcode.

5
maxisam

Oder Sie können #ngTasty als einfache Tabellenanweisung verwenden. Github: https://github.com/Zizzamia/ng-tasty Docs: http: // zizzamia. de/ng-delicious/richtlinie/tabelle

0
zizzamia

Ich denke, ein Teil Ihres Boilerplate-Codes für AngularJS, der speziell für die Einrichtung Ihres Controllers und Ihrer Factory verwendet wurde, hatte möglicherweise einen Syntaxfehler.

Hier ist ein Beispiel für die Arbeit mit Ihren Daten und eine Erweiterung der Sortiermethode für Tabellenspalten. Da AngularJS JavaScript-Datenstrukturen für die Anzeige in HTML gut verarbeiten kann, können Sie die JavaScript-Arrays im Speicher einfach neu anordnen, und AngularJS übernimmt die Änderungen. In diesem Beispiel können Sie auf die Überschriften der Tabelle klicken, wodurch eine Sortierung basierend auf dem Datentyp dieser Spalte ausgelöst wird. Wenn es bereits nach dieser Spalte sortiert ist, wird die Spalte in umgekehrter Reihenfolge sortiert. Die Typerkennung erfolgt über die vorgestellte isNumeric () -Funktion und eine kleine Änderung:

  1. Es wurde eine Überprüfung hinzugefügt, ob das Symbol '#' als Überschrift eingegeben und in der Methode toggleSort als Zahl sortiert wurde. Dies kann von Benutzern leicht entfernt werden, wenn dies gewünscht wird.
  2. Wenn toggleSort versucht, alphabetisch zu sortieren, wechselt es zum Sortieren nach Zahlen, wenn es einen TypeError abfängt.
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://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.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>

Ich habe ein funktionierendes Plunker-Beispiel zusammengestellt, um es zu demonstrieren. Klicken Sie einfach auf die Überschriften und sie sortieren das Array im Speicher, wo AngularJS die Änderungen aufnimmt und diesen Teil des DOM aktualisiert.

0
C.D.