Директива добавления разделителей для ng-repeat + поддержка последнего разделителя, отличного от основного
Ожидает приглашения
Зачастую нам приходится отображать данные, хранящиеся в массиве на сайте. Для отображения строковых данных мы, как правило, разделяем их запятой. В случае обыкновенной строки идеальным вариантом было бы простое использование JS функции
Для того, что бы наши элементы разделялись запятой, нам необходимо добавить запятую в тело шаблона
scope: false — не конфликтует с другими директивами
priority: 1001 — на 1 выше чем у
Для того, чтобы использовать директиву, необходимо добавить на элемент, содержащий
Если указать второй разделитель:
Вот Plunker с примером использования.
Директива подставляет в шаблон
Если у вас есть идеи, как можно улучшить данное решение, прошу комментировать.
Спасибо.
Array.join(', ')
. Но что делать в случае, если нам необходимо отобразить более сложные структуры? В большинстве случаев естественным выбором будет использование директивы AngularJS — ngRepeat
.Для того, что бы наши элементы разделялись запятой, нам необходимо добавить запятую в тело шаблона
ngRepeat
, отображаемую только в определённом случае. Шаблон директивы становится некрасивым и нагромождённым. К счастью, AngularJS позволяет нам инкапсулировать часть логики и манипуляции DOM в отдельную директиву. Именно такую директиву я написал для упрощения повседневной рутины с выводом строковых массивов, которой готов с вами поделиться.Основные свойства директивы
scope: false — не конфликтует с другими директивами
priority: 1001 — на 1 выше чем у
ngRepeat
, отрабатывается раньшеИспользование
Для того, чтобы использовать директиву, необходимо добавить на элемент, содержащий
ng-repeat
— атрибут ng-repeat-delimiter
. В качестве параметра указать разделитель в скобках. Например ng-repeat-delimiter="(, )"
. // Первый, Второй, Третий, ЧетвёртыйЕсли указать второй разделитель:
ng-repeat-delimiter="(, )( и )"
(cкобки нужны для того, что бы сохранить пробелы), он будет использован в качестве последнего. // Первый, Второй, Третий и Четвёртый. Вот Plunker с примером использования.
angular.module('ng.helpers').directive('ngRepeatDelimiter', ngRepeatDelimiter);
function ngRepeatDelimiter() {
return {
restrict: 'A',
priority: 1001, // на 1 выше чем у ng-repeat
compile: compile
};
function compile(element, attrs){
var delimAttr = attrs.ngRepeatDelimiter;
var re = /\((.[^)]+)/g;
var m;
var delimiters = [];
// забираем из атрибута первые 2 разделителя
while ((m = re.exec(delimAttr)) !== null && delimiters.length < 2) {
delimiters.push(m[1]);
if (m.index === re.lastIndex) {
re.lastIndex++;
}
}
if(delimiters.length == 0) return;
var delimiter = delimiters[0];
var lastDelimiter = delimiters[1];
// идём от обратного, добавляя разделитель в начало, если не первый элемент и,
// если есть второй разделитель - не последний элемент
var html = '<span ng-if="!$first' + (lastDelimiter ? ' && !$last' : '') + '">' + delimiter + '</span>';
// если есть второй разделитель
if(lastDelimiter){
// добавляем второй разделитель, если не первый и последний
html += '<span ng-if="$last && !$first">' + lastDelimiter + '</span>';
}
// заменяем исходный шаблон, убираем лишние пробелы
var newTemplate = html + element.html().trim();
element.html(newTemplate);
}
}
Директива подставляет в шаблон
ngRepeat
тег span
с разделителем, который скрывается или отображается посредством директивы ngIf
. На мой взгляд это наиболее чистое решение.Если у вас есть идеи, как можно улучшить данное решение, прошу комментировать.
Спасибо.