Подтвердить что ты не робот

Добавление строк с ng-repeat и вложенным циклом

Я ищу способ добавления строк в таблицу. Моя структура данных выглядит так:

  rows = [
    { name : 'row1', subrows : [{ name : 'row1.1' }, { name : 'row1.2' }] },
    { name : 'row2' }
  ];

Я хочу создать таблицу, которая выглядит так:

  table
     row1
     row1.1
     row1.2
     row2

Возможно ли это с помощью angular js ng-repeat? Если нет, то каким образом это будет

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

4b9b3361

Ответ 1

Вы не сможете сделать это с помощью ng-repeat. Однако вы можете сделать это с помощью директивы.

<my-table rows='rows'></my-table>

Fiddle.

myApp.directive('myTable', function () {
    return {
        restrict: 'E',
        link: function (scope, element, attrs) {
            var html = '<table>';
            angular.forEach(scope[attrs.rows], function (row, index) {
                html += '<tr><td>' + row.name + '</td></tr>';
                if ('subrows' in row) {
                    angular.forEach(row.subrows, function (subrow, index) {
                        html += '<tr><td>' + subrow.name + '</td></tr>';
                    });
                }
            });
            html += '</table>';
            element.replaceWith(html)
        }
    }
});

Ответ 2

Более года спустя, но нашел обходное решение, по крайней мере, для двух уровней (отцов → сыновей).
Просто повторите tbody 's:

<table>
  <tbody ng-repeat="row in rows">
    <tr>
      <th>{{row.name}}</th>
    </tr>
    <tr ng-repeat="sub in row.subrows">
      <td>{{sub.name}}</td>
    </tr>
  </tbody>
</table>

Насколько я знаю, все браузеры поддерживают несколько элементов tbody внутри таблицы.

Ответ 3

Более 3 лет спустя, я столкнулся с той же проблемой, и перед тем, как записать директиву, я попробовал это, и это сработало для меня:

<table>
    <tbody>
        <tr ng-repeat-start="row in rows">
            <td>
                {{ row.name }}
            </td>
        </tr>
        <tr ng-repeat-end ng-repeat="subrow in row.subrows">
            <td>
                {{ subrow.name }}
            </td>
        </tr>
    </tbody>
</table>

Ответ 4

Я немного удивлен, что многие из них выступают за пользовательские директивы и создают переменные прокси, обновляемые $watch.

Подобные проблемы являются причиной того, что были созданы фильтры AngularJS!

Из документов:

A filter formats the value of an expression for display to the user.

Мы не пытаемся манипулировать данными, просто отформатируем его для отображения по-другому. Поэтому сделаем фильтр, который принимает в нашем массиве строк, выравнивает его и возвращает сплющенные строки.

.filter('flattenRows', function(){
return function(rows) {
    var flatten = [];
    angular.forEach(rows, function(row){
      subrows = row.subrows;
      flatten.push(row);
      if(subrows){
        angular.forEach(subrows, function(subrow){
          flatten.push( angular.extend(subrow, {subrow: true}) );
        });
      }
    });
    return flatten;
}
})

Теперь нам нужно добавить фильтр в ngRepeat:

<table class="table table-striped table-hover table-bordered">
  <thead>
    <tr>
      <th>Rows with filter</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="row in rows | flattenRows">
          <td>{{row.name}}</td>
      </tr>
  </tbody>
</table>

Теперь вы можете комбинировать таблицу с другими фильтрами, если хотите, например, поиск.

В то время как подход с несколькими телами удобен и действителен, он испортит любой css, который опирается на порядок или индекс дочерних строк, таких как "полосатая" таблица, а также делает предположение, что вы не создали свой стиль чтобы вы не хотели повторять.

Здесь plunk: http://embed.plnkr.co/otjeQv7z0rifPusneJ0F/preview

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

Ответ 5

Да, возможно:

Контроллер:

app.controller('AppController',
    [
      '$scope',
      function($scope) {
        $scope.rows = [
          { name : 'row1', subrows : [{ name : 'row1.1' }, { name : 'row1.2' }] },
          { name : 'row2' }
        ];

      }
    ]
  );

HTML:

<table>
  <tr ng-repeat="row in rows">
    <td>
      {{row.name}}
      <table ng-show="row.subrows">
        <tr ng-repeat="subrow in row.subrows">
          <td>{{subrow.name}}</td>
        </tr>
      </table>
    </td>
  </tr>
</table>

Plunker

Если вы не хотите подтаблицы, сгладьте строки (в то время как аннотации подвих, чтобы можно было различать):

Контроллер:

function($scope) {
  $scope.rows = [
    { name : 'row1', subrows : [{ name : 'row1.1' }, { name : 'row1.2' }] },
    { name : 'row2' }
  ];

  $scope.flatten = [];
  var subrows;
  $scope.$watch('rows', function(rows){
    var flatten = [];
    angular.forEach(rows, function(row){
      subrows = row.subrows;
      delete row.subrows;
      flatten.push(row);
      if(subrows){
        angular.forEach(subrows, function(subrow){
          flatten.push( angular.extend(subrow, {subrow: true}) );
        });
      }
    });
    $scope.flatten = flatten;
  });

}

HTML:

<table>
  <tr ng-repeat="row in flatten">
    <td>
      {{row.name}}
    </td>
  </tr>
</table>

Plunker

Ответ 6

Вот пример. Этот код печатает все имена всех людей в массиве peopeByCity.

TS:

export class AppComponent {
  peopleByCity = [
    {
      city: 'Miami',
      people: [
        {
          name: 'John', age: 12
        }, {
          name: 'Angel', age: 22
        }
      ]
    }, {
      city: 'Sao Paulo',
      people: [
        {
          name: 'Anderson', age: 35
        }, {
          name: 'Felipe', age: 36
        }
      ]
    }
  ]
}

HTML:

<div *ngFor="let personsByCity of peopleByCity">
  <div *ngFor="let person of personsByCity.people">
    {{ person.name }}
  </div>
</div>