...

понедельник, 21 октября 2013 г.

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

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий