Использование запятой в качестве разделителя списка с AngularJS

179

Мне нужно создать список элементов через запятую:

  <li ng-repeat="friend in friends">
      <b ng-repeat="email in friend.email">{{email}}{{$last ? '' : ', '}}</b>...
  </li>

Согласно документации AngularJS, операторы потока управления не допускаются в выражениях. Вот почему мой {{$last ? '' : ', '}}не работает.

Есть ли альтернативный способ создания списков через запятую?

EDIT 1
есть что-то проще, чем:

<span ng-show="!$last">, </span>
Франк Фрайбургер
источник
5
Вы всегда можете использовать CSS для форматирования списков таким образом (то вам не нужно изменять HTML , когда ваш босс хочет , чтобы их на отдельные строки и т.д.) - см stackoverflow.com/questions/1517220/...
AlexFoxGill

Ответы:

338

Вы могли бы сделать это так:

<b ng-repeat="email in friend.email">{{email}}{{$last ? '' : ', '}}</b>

..Но мне нравится ответ Филиппа :-)

Эндрю Джослин
источник
Не должно ($last && '' || ', ')всегда уступать ', '?
Okm
15
Как и выше, я не могу угадать, как правильно оценить $ last to true или false в шаблоне. Я использовал это: {{{true: '', false: ', '}[$last]}}. Этот метод более гибкий, чем использование, .joinпотому что он позволяет элементам в списке быть членами массива, например:<b ng-repeat="friend in friends">{{friend.email}}{{{true: '', false: ', '}[$last]}}</b>
Ryan Marcus
3
Обновлено для использования троичных операторов
Эндрю Джослин
1
Как я могу вставить и в печатный массив так, чтобы мой массив выглядел так: Джон, Майк и Нил. Как получить этот формат без использования директивы.
MaTya
Я использую этот подход, поскольку он позволяет мне использовать фильтр для каждого значения в списке.
C Fairweather
231

Просто используйте встроенную join(separator)функцию Javascript для массивов:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>
Филипп Рейхарт
источник
21
Если вы хотите использовать разделители HTML-кода, возможно, пришло время написать директиву . Вы также можете вставить HTML-код join()и отключить экранирование HTML, но для этого в аду есть специальное место;)
Филипп Рейхарт
Хорошо, я даже не думал об этом.
Клубника
@DavidKEgghead, я позволю себе не согласиться, jsfiddle.net/wuZRA . Как это не работает для вас?
Филипп Рейхарт
2
@PhilippReichart извините за задержку. Вот пример: jsfiddle.net/Sek8F - похоже, что вы нацеливаетесь на строку, где я имею в виду объект.
Рави Рам
101

Также:

angular.module('App.filters', [])
    .filter('joinBy', function () {
        return function (input,delimiter) {
            return (input || []).join(delimiter || ',');
        };
    });

И в шаблоне:

{{ itemsArray | joinBy:',' }}
sanusart
источник
11
Этот ответ показывает «угловой путь» и должен быть отмечен как лучший.
Евгений Грязнов
14
Почему бы не сохранить шесть строк и просто сделать {{ itemsArray.join(', ') }}?
Филипп Рейхарт
12
Я не уверен, что переписать основные функции JavaScript в AngularJS - это действительно "угловой путь" ...
Майкл Коул,
1
Этот ответ показывает, как Angular может повысить ценность массивов объектов
Майкл Коул,
41

.list-comma::before {
  content: ',';
}
.list-comma:first-child::before {
  content: '';
}
<span class="list-comma" ng-repeat="destination in destinations">
                            {{destination.name}}
                        </span>

Simbu
источник
1
Это кажется наиболее "семантическим" способом, поскольку выбор использования списка через запятую целиком зависит от представления. С таким же успехом это мог быть подсписок.
Эллиот Камерон
Это было первое решение, которое пришло мне в голову. Менее зависит от JavaScript.
Kalpesh
10

Вы можете использовать CSS, чтобы исправить это тоже

<div class="some-container">
[ <span ng-repeat="something in somethings">{{something}}<span class="list-comma">, </span></span> ]
</div>

.some-container span:last-child .list-comma{
    display: none;
}

Но ответ Энди Джослина лучший

Изменить: я передумал, я должен был сделать это недавно, и я в конечном итоге пошел с фильтром соединения.

Крис Стивенс
источник
2
Я бы тоже выбрал пользовательский фильтр, но мне нравится твоя идея :)
JBC
5

Я думаю, что лучше использовать ng-if. ng-showсоздает элемент в domи устанавливает его display:none. Чем больше domэлементов у вас есть, тем больше ресурсов требует ваше приложение, а на устройствах с меньшими ресурсами меньше domэлементов - тем лучше.

TBH <span ng-if="!$last">, </span>кажется отличным способом сделать это. Это просто.

the7erm
источник
Мне нравится этот подход, поскольку он прост и все еще поддерживает разделители на основе HTML. Спасибо @ the7erm!
alexkb
2

Поскольку этот вопрос довольно старый и AngularJS успел развиться с тех пор, это теперь легко можно сделать с помощью:

<li ng-repeat="record in records" ng-bind="record + ($last ? '' : ', ')"></li>,

Обратите внимание, что я использую ngBindвместо интерполяции, {{ }}поскольку он намного более производительный: ngBind будет работать только тогда, когда переданное значение действительно изменится. Скобки {{ }}, с другой стороны, будут проверяться и обновляться в каждом $ дайджесте, даже если в этом нет необходимости. Источник: здесь , здесь и здесь .

angular
  .module('myApp', [])
  .controller('MyCtrl', ['$scope',
    function($scope) {
      $scope.records = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    }
  ]);
li {
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
  <ul>
    <li ng-repeat="record in records" ng-bind="record + ($last ? '' : ', ')"></li>
  </ul>
</div>

В заключение отметим, что все решения здесь работают и действуют по сей день. Я действительно нашел тех, кто использует CSS, так как это больше вопрос презентации.

Космин Абабей
источник
1

Мне нравится подход симбу, но мне неудобно использовать первого или последнего ребенка. Вместо этого я изменяю только содержимое повторяющегося списка через запятую.

.list-comma + .list-comma::before {
    content: ', ';
}
<span class="list-comma" ng-repeat="destination in destinations">
    {{destination.name}}
</span>
Durrahan
источник
0

Если вы используете ng-show для ограничения значений, это {{$last ? '' : ', '}}не сработает, поскольку все равно будут учитываться все значения. Пример

<div ng-repeat="x in records" ng-show="x.email == 1">{{x}}{{$last ? '' : ', '}}</div>

var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope) {
  $scope.records = [
    {"email": "1"},
    {"email": "1"},
    {"email": "2"},
    {"email": "3"}
  ]
});

Результатом является добавление запятой после «последнего» значения , поскольку при использовании ng-show все равно учитываются все 4 значения

{"email":"1"},
{"email":"1"},

Одним из решений является добавление фильтра непосредственно в ng-repeat

<div ng-repeat="x in records | filter: { email : '1' } ">{{x}}{{$last ? '' : ', '}}</div>

Полученные результаты

{"email":"1"},
{"email":"1"}
Михай
источник
Любое предложение о том, как решить эту проблему таким же образом в Angular 2, не создавая пользовательский канал?
chaenu