AngularJS ng-repeat, запятая, разделенная "и" перед последним пунктом

У меня есть список элементов...

$scope.Users =[{
    UserName: ''
}];

На мой взгляд, я хочу их перечислить, если предположить, что у меня есть только 4 элемента в $scope:Users

Username1, Username2, Username3 and Username4

<span data-ng-repeat="user in Users">{{user.Username}}</span>{{$last ? '' : ', '}}

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

Моя проблема заключается в том, как добавить ключевое слово and до последнего элемента, чтобы он выглядел следующим образом:

Username1, Username2, Username3 and Username4

вместо:

Username1, Username2, Username3, Username4

Ответ 1

$last - это истинное значение.. поэтому он содержит либо true, либо false и не содержит последний индекс элемента.

Я думаю, ниже выражение должно решить вашу проблему

<p><span ng-repeat="user in Users">
            {{user.Username}} {{$last ? '' : ($index==Users.length-2) ? ' and ' : ', '}}
  </span></p>

Также убедитесь, что у вас есть выражение с $last в элементе ng-repeat, а не вне него

Пожалуйста, проверьте приведенный ниже рабочий скрипт

http://jsfiddle.net/hrishi1183/Sek8F/2/

Ответ 2

<span ng-repeat="user in Users">{{$first ? '' : $last ? ' and ' : ', '}}{{user.Username}}</span>

Вместо добавления чего-либо добавьте его. Вы можете использовать $first, чтобы опустить первый. Затем вы можете использовать $last для добавления "и" вместо запятой.

Ответ 3

Это может быть одно из решений

<span data-ng-repeat="user in Users">{{user.Username}}<font ng-show="!$last">,</font></span>

Ответ 4

Используйте запятую до и для повышения ясности!

Билл Гейтс жертвует 6 миллионов на Username1, Username2 и Username3.

vs

Билл Гейтс пожертвовал 6 миллионов для Username1, Username2 и Username3.

Без последовательной запятой в предложении явно не указывается, что каждому из пользователей должна быть предоставлена ​​равная доля.

<span ng-repeat="user in Users">
     {{user.Username}}{{$last ? '' : ($index==Username.length-2) ? ', and ' : ',&nbsp;'}}
</span>

Выходы:

Username1, Username2, Username3, and Username4

Ответ 5

Если вам просто нужен текстовый вывод, используйте вместо него ng-repeat настраиваемый фильтр:

<span>{{Users | humanizedUserList}}</span>

код фильтра выглядит примерно так (используя Lodash):

app.filter('humanizedUserList', function() {
  return function(users) {
    var last_users = _.last(users, 2);
    return _.reduce(users, function(out, user, idx, users) {
      out += user.UserName;

      if(user === last_users[1]) { // last entry
        return out;
      }
      else if(user === last_users[0]) { // second to last entry
        return out + ', and ';
      }
      else {
        return out + ', ';
      }
    });
  };
}

Вы избавитесь от хакерского использования $last вне ng-repeat и тройных операторов - и добавьте повторное использование для других частей вашего приложения.

Ответ 6

Сегодня я столкнулся с этой проблемой, но с дополнительной проблемой, чтобы элементы списка могли быть отформатированы в предложении (например, жирные элементы или ссылки). Поэтому просто вывод строки из фильтра не будет работать. Сначала я попытался использовать ng-bind-html и вывел HTML из фильтра, но это было недостаточно гибким.

В итоге я создал директиву, которая может использоваться в любом ng-repeat, чтобы добавить разделитель между элементами списка. Сложная часть: у меня только был доступ к $first, $last и $index (а не к исходному массиву или его длине!).

Мое решение:

var app = angular.module('app', []);
app.directive('listSeparator', function() {
  return {
    replace: true,
    template: '<span>{{ separator }}</span>',
    link: function(scope, elem, attrs) {
      scope.$watchGroup(["$index", "$first", "$last"], function() {
        if (scope.$first)
          scope.separator = "";
        else if (scope.$last && scope.$index == 1)
          scope.separator = " and ";
        else if (scope.$last)
          scope.separator = ", and ";
        else
          scope.separator = ",";
      })
    }
  }
})
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"></script>
<div ng-app="app">
    Click a button to see the formatted list.
    <button ng-click="myArray = ['one']">One item</button>
    <button ng-click="myArray = ['one','two']">Two items</button>
    <button ng-click="myArray = ['one','two','three']">Three items</button><br>
    <span ng-repeat="item in myArray"><list-separator></list-separator>
        <strong>{{item}}</strong></span>

</div>