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 и выше. И с русским текстом тоже работает. Более подробные комментарии и описание синтаксиса смотрите в исходных кодах примеров. Вопросы, предложения и конструктивная критика и помощь более чем приветствуются.

Ваше мнение

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

Проголосовал 1 человек. Воздержавшихся нет.

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

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

Никто ещё не голосовал. Воздержался 1 человек.

ссылка на оригинал статьи http://habrahabr.ru/post/197646/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *