AngularJS сортировка строк по заголовку таблицы

У меня есть четыре заголовка таблицы:

$scope.headers = ["Header1", "Header2", "Header3", "Header4"];

И я хочу, чтобы иметь возможность сортировать мою таблицу, нажав на заголовок.

Итак, если моя таблица выглядит так

H1 | H2 | H3 | H4
A    H    D   etc....
B    G    C
C    F    B
D    E    A

и я нажимаю

H2

Теперь моя таблица выглядит так:

H1 | H2 | H3 | H4
D    E    A   etc....
C    F    B
B    G    C
A    H    D

То есть содержимое каждого столбца никогда не изменяется, но, щелкнув заголовок, я хочу заказать столбцы, строки будут переупорядочиваться.

Содержимое моей таблицы создается вызовом базы данных, выполненным с помощью Mojolicious и возвращается в браузер с помощью

$scope.results = angular.fromJson(data); // This works for me so far

Остальная часть кода, который я вымотал, выглядит примерно так:

<table class= "table table-striped table-hover">
    <th ng-repeat= "header in headers">
        <a> {{headers[$index]}} </a>
    </th>
    <tr ng-repeat "result in results">
        <td> {{results.h1}} </td>
        <td> {{results.h2}} </td>
        <td> {{results.h3}} </td>
        <td> {{results.h4}} </td>
    </tr>
</table>

Как упорядочить столбцы с этой точки, просто щелкнув заголовок в верхней части таблицы?

Ответ 1

Я думаю, что этот рабочий пример CodePen, который я создал, покажет вам, как сделать то, что вы хотите.

Шаблон:

<section ng-app="app" ng-controller="MainCtrl">
  <span class="label">Ordered By: {{orderByField}}, Reverse Sort: {{reverseSort}}</span><br><br>
  <table class="table table-bordered">
    <thead>
      <tr>
        <th>
          <a href="#" ng-click="orderByField='firstName'; reverseSort = !reverseSort">
          First Name <span ng-show="orderByField == 'firstName'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
          </a>
        </th>
        <th>
          <a href="#" ng-click="orderByField='lastName'; reverseSort = !reverseSort">
            Last Name <span ng-show="orderByField == 'lastName'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
          </a>
        </th>
        <th>
          <a href="#" ng-click="orderByField='age'; reverseSort = !reverseSort">
          Age <span ng-show="orderByField == 'age'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
          </a>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="emp in data.employees|orderBy:orderByField:reverseSort">
        <td>{{emp.firstName}}</td>
        <td>{{emp.lastName}}</td>
        <td>{{emp.age}}</td>
      </tr>
    </tbody>
  </table>
</section>

Код JavaScript:

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope) {
  $scope.orderByField = 'firstName';
  $scope.reverseSort = false;

  $scope.data = {
    employees: [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    },{
      firstName: 'Frank',
      lastName: 'Burns',
      age: 54
    },{
      firstName: 'Sue',
      lastName: 'Banter',
      age: 21
    }]
  };
});

Ответ 2

Вот скрипка, которая поможет вам сделать это с помощью AngularJS
http://jsfiddle.net/patxy/D2FsZ/

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

Тогда что-то вроде этого для ваших данных:

<tr ng:repeat="row in body.$orderBy(sort.column, sort.descending)">
    <td>{{row.a}}</td>
    <td>{{row.b}}</td>
    <td>{{row.c}}</td>
</tr>

С такими функциями в вашем контроллере AngularJS:

scope.sort = {
    column: 'b',
    descending: false
};

scope.selectedCls = function(column) {
    return column == scope.sort.column && 'sort-' + scope.sort.descending;
};

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

Ответ 3

Другим способом сделать это в AngularJS является использование Grid.

Преимущество сетки заключается в том, что поведение сортировки строк, которое вы ищете, включено по умолчанию.

Функциональность хорошо инкапсулирована. Вам не нужно добавлять атрибуты ng-click или использовать переменные области видимости для поддержания состояния:

    <body ng-controller="MyCtrl">
        <div class="gridStyle" ng-grid="gridOptions"></div>
    </body>

Вы просто добавляете параметры сетки в свой контроллер:

  $scope.gridOptions = {
    data: 'myData.employees',
    columnDefs: [{
      field: 'firstName',
      displayName: 'First Name'
    }, {
      field: 'lastName',
      displayName: 'Last Name'
    }, {
      field: 'age',
      displayName: 'Age'
    }]
  };

Полный рабочий фрагмент прилагается:

var app = angular.module('myApp', ['ngGrid', 'ngAnimate']);
app.controller('MyCtrl', function($scope) {

  $scope.myData = {
    employees: [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    }, {
      firstName: 'Frank',
      lastName: 'Burns',
      age: 54
    }, {
      firstName: 'Sue',
      lastName: 'Banter',
      age: 21
    }]
  };

  $scope.gridOptions = {
    data: 'myData.employees',
    columnDefs: [{
      field: 'firstName',
      displayName: 'First Name'
    }, {
      field: 'lastName',
      displayName: 'Last Name'
    }, {
      field: 'age',
      displayName: 'Age'
    }]
  };
});
/*style.css*/
.gridStyle {
    border: 1px solid rgb(212,212,212);
    width: 400px;
    height: 200px
}
<!DOCTYPE html>
<html ng-app="myApp">
    <head lang="en">
        <meta charset="utf-8">
        <title>Custom Plunker</title>
        <link rel="stylesheet" type="text/css" href="http://angular-ui.github.com/ng-grid/css/ng-grid.css" />
        <link rel="stylesheet" type="text/css" href="style.css" />
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular-animate.js"></script>
        <script type="text/javascript" src="http://angular-ui.github.com/ng-grid/lib/ng-grid.debug.js"></script>
        <script type="text/javascript" src="main.js"></script>
    </head>
    <body ng-controller="MyCtrl">
        <div class="gridStyle" ng-grid="gridOptions"></div>
    </body>
</html>

Ответ 4

Вот пример, который сортируется по заголовку. Эта таблица динамична и изменяется с размером JSON.

Мне удалось создать динамическую таблицу для некоторых других примеров и документации. http://jsfiddle.net/lastlink/v7pszemn/1/

<tr>
    <th class="{{header}}" ng-repeat="(header, value) in items[0]" ng-click="changeSorting(header)">
    {{header}}
  <i ng-class="selectedCls2(header)"></i>
</tr>

<tbody>
    <tr ng-repeat="row in pagedItems[currentPage] | orderBy:sort.sortingOrder:sort.reverse">
        <td ng-repeat="cell in row">
              {{cell}}
       </td>
    </tr>

Хотя столбцы не соответствуют порядку, в моем .NET-проекте они находятся в порядке.

Ответ 5

Вы можете использовать этот код без стрелок..... i.e, нажав на заголовок, он автоматически показывает возрастающий и убывающий порядок элементов.

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="scripts/angular.min.js"></script>
    <script src="Scripts/Script.js"></script>
    <style>
        table {
            border-collapse: collapse;
            font-family: Arial;
        }

        td {
            border: 1px solid black;
            padding: 5px;
        }

        th {
            border: 1px solid black;
            padding: 5px;
            text-align: left;
        }
    </style>
</head>
<body ng-app="myModule">
    <div ng-controller="myController">

        <br /><br />
        <table>
            <thead>
                <tr>
                    <th>
                        <a href="#" ng-click="orderByField='name'; reverseSort = !reverseSort">
                            Name
                        </a>
                    </th>
                    <th>
                        <a href="#" ng-click="orderByField='dateOfBirth'; reverseSort = !reverseSort">
                            Date Of Birth
                        </a>
                    </th>
                    <th>
                        <a href="#" ng-click="orderByField='gender'; reverseSort = !reverseSort">
                           Gender
                        </a>
                    </th>
                    <th>
                        <a href="#" ng-click="orderByField='salary'; reverseSort = !reverseSort">
                            Salary
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="employee in employees | orderBy:orderByField:reverseSort">
                    <td>
                        {{ employee.name }}
                    </td>
                    <td>
                        {{ employee.dateOfBirth | date:"dd/MM/yyyy" }}
                    </td>
                    <td>
                        {{ employee.gender }}
                    </td>
                    <td>
                        {{ employee.salary  }}
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
        var app = angular
        .module("myModule", [])
        .controller("myController", function ($scope) {

            var employees = [
                {
                    name: "Ben", dateOfBirth: new Date("November 23, 1980"),
                    gender: "Male", salary: 55000
                },
                {
                    name: "Sara", dateOfBirth: new Date("May 05, 1970"),
                    gender: "Female", salary: 68000
                },
                {
                    name: "Mark", dateOfBirth: new Date("August 15, 1974"),
                    gender: "Male", salary: 57000
                },
                {
                    name: "Pam", dateOfBirth: new Date("October 27, 1979"),
                    gender: "Female", salary: 53000
                },
                {
                    name: "Todd", dateOfBirth: new Date("December 30, 1983"),
                    gender: "Male", salary: 60000
                }
            ];

            $scope.employees = employees;
            $scope.orderByField = 'name';
            $scope.reverseSort = false;

        });
    </script>
</body>
</html>

Ответ 6

Используйте стороннюю библиотеку JavaScript. Это даст вам это и многое другое. Хорошим примером является datatables (если вы также используете jQuery): https://datatables.net

Или просто закажите связанный массив в $scope.results при щелчке заголовка.

Ответ 7

Я просто мочу ноги с помощью angular, но я нашел этот отличный учебник.
Здесь работает plunk Я сослался на кредит Скотту Аллену и вышеупомянутому учебнику. Нажмите "Поиск", чтобы отобразить отсортированную таблицу.

Для каждого заголовка столбца вам нужно сделать его кликабельным - ng-click по ссылке будет работать. Это приведет к сортировке sortName столбца.

<th>
     <a href="#" ng-click="sortName='name'; sortReverse = !sortReverse">
          <span ng-show="sortName == 'name' && sortReverse" class="glyphicon glyphicon-triangle-bottom"></span>
          <span ng-show="sortName == 'name' && !sortReverse" class="glyphicon glyphicon-triangle-top"></span>
           Name
     </a>
</th>

Затем в теле таблицы вы можете передать в этом sortName в orderBy filter orderBy: sortName: sortReverse

<tr ng-repeat="repo in repos | orderBy:sortName:sortReverse | filter:searchRepos">
     <td>{{repo.name}}</td>
     <td class="tag tag-primary">{{repo.stargazers_count | number}}</td>
     <td>{{repo.language}}</td>
</tr>

Ответ 8

----Try this----

First change your controller

yourModuleName.controller("yourControllerName", function ($scope) {
    var list = [
        { H1:'A', H2:'B', H3:'C', H4:'d' },
        { H1:'E', H2:'B', H3:'F', H4:'G' },
        { H1:'C', H2:'H', H3:'L', H4:'M' },
        { H1:'I', H2:'B', H3:'E', H4:'A' }
    ];

    $scope.list = list;

    $scope.headers = ["Header1", "Header2", "Header3", "Header4"];

    $scope.sortColumn = 'Header1';

    $scope.reverseSort = false;

    $scope.sortData = function (columnIndex) {
        $scope.reverseSort = ($scope.sortColumn == $scope.headers[columnIndex]) ? !$scope.reverseSort : false;

        $scope.sortColumn = $scope.headers[columnIndex];
    }

});

then change code in html side like this

<th ng-repeat= "header in headers">
        <a ng-click="sortData($index)"> {{headers[$index]}} </a>
    </th>
    <tr ng-repeat "result in results | orderBy : sortColumn : reverseSort">
        <td> {{results.h1}} </td>
        <td> {{results.h2}} </td>
        <td> {{results.h3}} </td>
        <td> {{results.h4}} </td>
    </tr>

Ответ 9

Я нашел самый простой способ решить этот вопрос. Если вы эффективны, вы можете использовать

Код HTML: import angular.min.js и библиотека angular.route.js

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>like/dislike</title>
</head>
<body ng-app="myapp" ng-controller="likedislikecntrl" bgcolor="#9acd32">
<script src="./modules/angular.min.js"></script>
<script src="./modules/angular-route.js"></script>
<script src="./likedislikecntrl.js"></script>
</select></h1></p>
<table border="5" align="center">
<thead>
<th>professorname <select ng-model="sort1" style="background-color: 
chartreuse">
<option value="+name" >asc</option>
<option value="-name" >desc</option>
</select></th>
<th >Subject <select ng-model="sort1">
<option value="+subject" >asc</option>
<option value="-subject" >desc</option></select></th>
<th >Gender <select ng-model="sort1">
<option value="+gender">asc</option>
<option value="-gender">desc</option></select></th>
<th >Likes <select ng-model="sort1">
<option value="+likes" >asc</option>
<option value="-likes" >desc</option></select></th>
<th >Dislikes <select ng-model="sort1">
<option value="+dislikes" >asc</option>
<option value="-dislikes">desc</option></select></th>
<th rowspan="2">Like/Dislike</th>
</thead>
<tbody>
<tr ng-repeat="sir in sirs | orderBy:sort1|orderBy:sort|limitTo:row" >
<td >{{sir.name}}</td>
<td>{{sir.subject|uppercase}}</td>
<td>{{sir.gender|lowercase}}</td>
<td>{{sir.likes}}</td>
<td>{{sir.dislikes}}</td>
<td><button ng-click="ldfi1(sir)" style="background-color:chartreuse" 
>Like</button></td>
<td><button ng-click="ldfd1(sir)" style="background-
color:chartreuse">Dislike</button></td>
</tr>
</tbody>
</table>
</body> 
</html>
JavaScript Code::likedislikecntrl.js

var app=angular.module("myapp",["ngRoute"]);

app.controller("likedislikecntrl",function ($scope) {
var sirs=[
    {name:"Srinivas",subject:"dmdw",gender:"male",likes:0,dislikes:0},
    {name:"Sharif",subject:"dms",gender:"male",likes:0,dislikes:0},
    {name:"Chaitanya",subject:"daa",gender:"male",likes:0,dislikes:0},
    {name:"Pranav",subject:"wt",gender:"male",likes:0,dislikes:0},
    {name:"Anil Chowdary",subject:"ds",gender:"male",likes:0,dislikes:0},
    {name:"Rajesh",subject:"mp",gender:"male",likes:0,dislikes:0},
    {name:"Deepak",subject:"dld",gender:"male",likes:0,dislikes:0},
    {name:"JP",subject:"mp",gender:"male",likes:0,dislikes:0},
    {name:"NagaDeepthi",subject:"oose",gender:"female",likes:0,dislikes:0},
    {name:"Swathi",subject:"ca",gender:"female",likes:0,dislikes:0},
    {name:"Madavilatha",subject:"cn",gender:"female",likes:0,dislikes:0}



]
$scope.sirs=sirs;
$scope.ldfi1=function (sir) {
    sir.likes++

}
$scope.ldfd1=function (sir) {
   sir.dislikes++

}
$scope.row=8;

})