AngularJS: еще одна таблица с сортировкой, фильтрацией и постраничной навигацией

Что это?


Это очередное AngularJS приложение, которое добавляет в обычную таблицу возможности сортировки, фильтрации, разбиения на страницы и пр.

Разумеется, существует несколько готовых решений (1, 2, 3, 4, 5), но они не подходили по ряду причин. В итоге, было решено создать свой вариант, тем более, что я не имею большого работы с AngularJS, а изучать этот фреймворк и его потрясающие возможности лучше на практике.

Предупреждаю сразу: исходный код не совсем «причёсан», местами не комментирован, и не так элегантен, как хотелось бы; возможно, я не использовал какие то best practices. Но т.к. я планирую постоянно использовать это решение и развивать его, то со временем всё будет. Также надеюсь на ваши советы, предложения и пожелания. Тем не менее, это вполне работоспособное приложение, и оно уже используется в наших проектах. В статье не буду расписывать подробно все-все-все возможности и настройки — это уже сделано в исходном коде примеров, остановлюсь на самых, как мне кажется, важных.
Исходники на github, документация и примеры.

Для чего?


  • Мы хотим разрабатывать прототип приложения быстро, нет времени на разработку серверной версии таблицы (списка) с сортировкой, фильтрами и постраничной навигацией. Поэтому, все данные таблицы находятся на клиенте, нет необходимости обращаться к серверу.
  • Верстальщик не обязан знать AngularJS
  • Вёрстка таблицы должна максимально соответствовать обычному HTML, а не быть нагромождением директив. Поменьше магии, пожалуйста.
  • Не ограничивать использование других Angular директив в разметке.
  • «Живой» поиск по списку, когда записи фильтруются по мере набора искомого текста.
  • Возможность фильтровать не по всем колонкам, а по выборочным.
  • Возможность написать свой фильтр.
  • Нужна возможность постраничной навигации.
  • Сортировка колонок.
  • Свобода в изменении HTML-кода таблицы, и вообще кода, связанного с таблицей.
  • Изучение AngularJS


Структура таблицы


<div id="testApp">
	
	<!-- Директива, внутри которой будет наша таблица -->
	<solo-table items-on-page = "10">
		<!-- Здесь данные для отображения в формате JSON, например -->		
		<div solo-table-data>
		[{
			"id": 1,
			"name": "Alvah Gleason",
			"address": "58707 Ophelia FieldEast Lorena, LA 89754-9301",
			"year": "1981"
		}, ......]       
		</div>
		
		<!-- Отображаем сколько есть страниц и на какой находимся -->
		<div>
			Page <[pager.currentPage]> of <[pager.foundPages]>. 
			Total items:  <[pager.found]>
		</div>

		<!-- Разметка таблицы -->
		<table class="table table-striped table-bordered" >
			<thead>
				<tr>				
					<th>Id</th>
					<th>Year</th>
					<th>Name</th>
					<th>Address</th>
				</tr>
			</thead>

			<!-- Рисуем строки с данными -->
			<tr ng-repeat="item in filtered = (original)" >
				<td><[item.id]></td>
				<td><[item.year]></td>
				<td><[item.name]></td>
				<td><[item.address]></td>
			</tr>

		</table>

		<!-- Постраничная навигация -->
		<div>
			<a href="" ng-click="gotoFirstPage()">First page | </a>
			<a href="" ng-click="gotoPrevPage()"> ←prev | </a>
			<a href="" ng-click="gotoNextPage()">next → | </a>
			<a href="" ng-click="gotoLastPage()">Last page </a>
		</div>
	</solo-table>
</div>
<script>
    // Здесь приведен код, упрощающий создание нового AngularJS приложения
    // Создаем приложение с именем example, вставляем его в элемент testApp,
    // добавляем в него таблицу и собственные фильтры
    AppFactory("testApp", "example", ["solo.table"]);

</script>

Как вы заметили, в коде используется синтаксис связывания <[ ]> вместо {{ }}. Мы используем Smarty в своих проектах и чтобы избежать конфликтов, пришлось внести некоторые изменения в конфигурацию приложения. Впрочем, вы вольны изменить или вообще не использовать AppFactory и применять родной синтаксис Angular.
Код AppFactory
/**
 * Создание нового Angular приложения с заданными настройками.
 * Позволяет разместить на одной странице несколько приложений.
 *
 * @param elementId ID DOM-элемента, к которому прикрепляется приложение
 * @param appName Имя приложения (главного модуля)
 * @param modules Список модулей, подключаемых к приложению
 * @constructor
 */
var AppFactory = function(elementId, appName, modules)
{
	'use strict';

	if (!modules)
		modules = [];
	var el = document.getElementById(elementId);
	angular.module(appName, modules).config([

		/**
		 * Т.к. используется Smarty, то символы {{ и }} нужно заменить,
		 * например, на <[ и ]>
		 */
		"$interpolateProvider", function($interpolateProvider){
			$interpolateProvider.startSymbol('<[');
			$interpolateProvider.endSymbol(']>');
		}
	]);
	modules.push(appName);
	angular.bootstrap(el, modules);
};



Сортировка колонок


Сортировка появляется в таблице, если добавить атрибут make-sotrable:
<solo-table items-on-page = "10" make-sortable>

Есть 2 режима:
ASC+DESC — сортировка по убыванию или возрастанию значения (по умолчанию)
<thead>
	<tr>
		<!-- У каждой колонки, которую мы хотим сортировать,
		нужно указать директиву sort-by='имя_поля' -->
		<th sort-by='id'>Id</th>
		<th sort-by='name'>Name</th>
		<th>Address</th>
	</tr>
</thead>

DEFAULT+ASC+DESC — сортировка по-умолчанию, убыванию или возрастанию значения. «По-умолчанию» — это означает, что данные будут показаны в том порядке, в котором они были предоставлены приложению. Кликая на заголовок колонки, вы можете отсортировать данные в 3-х этих направлениях. Для этого нужно присвоить значение «3» атрибуту make-sortable:
<solo-table items-on-page = "10" make-sortable="3">

А если хочется, чтобы одна колонка была сразу отсортирована в каком то направлении, то используем default-sort, обратите внимание что эту директиву можно применить только к одной колонке таблицы (во всяком случае, пока):
<th sort-by='name' default-sort="asc">Name</th>

Для отображения указателей сортировки в заголовках не забудьте вставить CSS, ну или свою реализацию
CSS код
	
		.solo-table-sort-asc > .solo-column-arrow
		{
			position: relative;
			top: 10px;
			margin-left: 5px;
			border-color: black transparent;
			border-style: solid;
			border-width: 5px 5px 0px 5px;
			height: 0px;
			width: 0px;
		}
		.solo-table-sort-desc > .solo-column-arrow
		{
			position: relative;
			top: -10px;
			margin-left: 5px;
			border-color: black transparent;
			border-style: solid;
			border-width: 0px 5px 5px 5px;
			height: 0px;
			width: 0px;
		}

		.solo-table-column-cursor
		{
			cursor: pointer;
		}



Используем собственный фильтр


Для этого нужно создать свой модуль с реализацией фильтра и подключить его к приложению. В этом примере используется фильтр по году: показываются только те записи, которые имеют поле year старше заданного (см. пример #5).

<script>

    // Создаем модуль с фильтрами
    angular.module("myFilters", [])

        // Показывать только те записи, которые имеют поле year старше заданного
        .filter("older", function(){
            return function(items, search){
                if (!search)
                    return items;
                search = parseInt(search);
                var test = function(el, idx, array){
                    return el.year > search;
                };
                return items.filter(test);
            };
    });
    // подключить модуль с фильтрами 
    AppFactory("testApp", "example", ["solo.table", "myFilters"]);

</script>

А также добавить этот фильтр в ng-repeat, где filterModel — имя модели, привязанной к input:
<tr ng-repeat="item in filtered = (original | older:filterModel)" >

А вот так мы можем фильтровать только по полям name и address (См. пример #6):
<tr ng-repeat="item in filtered = (original | filterByFields:filterModel:['name', 'address'])" >

В планах


  • Больше примеров
  • Сохранение параметров таблица в URL
  • Возможность применения не только к таблицам, а спискам из любых DOM-элементов (UL>LI, div и пр.)
  • ...

Что-то еще?


Да. Это всё работает с версией AngularJS 1.1.5 и выше. И с русским текстом тоже работает. Более подробные комментарии и описание синтаксиса смотрите в исходных кодах примеров. Вопросы, предложения и конструктивная критика и помощь более чем приветствуются.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Ваше мнение

  • 64.6%Полезно42
  • 16.9%Бесполезно11
  • 18.4%Мне все равно12

Я уже использую

  • 3.3%http://lorenzofox3.github.io/smart-table-website/1
  • 13.3%http://angulartable.com/4
  • 0%https://github.com/ssmm/angular-table0
  • 26.6%http://angular-ui.github.io/ng-grid8
  • 20%http://esvit.github.io/ng-table6
  • 36.6%Свой вариант11
  • +7
  • 37,4k
  • 2
Поделиться публикацией

Комментарии 2

    0
    Написал пожелания на github issue #1
    Буду следить за проэктом. Спасибо.
      0
      В следующей версии планировал сделать подобную возможность

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое