Что это?
Это очередное 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.
/** * Создание нового 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, ну или свою реализацию
.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 и выше. И с русским текстом тоже работает. Более подробные комментарии и описание синтаксиса смотрите в исходных кодах примеров. Вопросы, предложения и конструктивная критика и помощь более чем приветствуются.
ссылка на оригинал статьи http://habrahabr.ru/post/197646/
Добавить комментарий