Как использовать шаблоны Angular2 с *ngFor для создания таблицы из вложенных массивов?

Учитывая следующий массив в свойстве компонента groups:

[
   {
     "name": "pencils",
     "items": ["red pencil","blue pencil","yellow pencil"]
   },
   {
     "name": "rubbers",
     "items": ["big rubber","small rubber"]
   },
]

Как создать html-таблицу со всеми элементами, каждый в одной строке? Ожидаемый результат HTML:

<table>
    <tr><td><h1>pencils</h1></td></tr>
    <tr><td>red pencil</td></tr>
    <tr><td>blue pencil</td></tr>
    <tr><td>yellow pencil</td></tr>
    <tr><td><h1>rubbers</h1></td></tr>
    <tr><td>big rubber</td></tr>
    <tr><td>small rubber</td></tr>
</table>

Первый уровень простой:

<table>
    <tr *ngFor="#group of groups">
        <td><h1>{{group.name}}</h1></td>
    </tr>
</table>

Но теперь мне нужно повторить #item of group. Проблема в том, что мне нужны новые элементы <tr> после элемента </tr>, который определяет group, не внутри.

Есть ли какое-либо решение для подобных проблем в шаблонах Angular2? Я бы ожидал какой-то специальный тег, который я мог бы использовать вместо <tr>, который не прописан в dom. Что-то похожее на фасеты и фрагменты в JSF.


person Witek    schedule 29.02.2016    source источник
comment
Можете ли вы добавить вывод HTML, который вы ожидаете в качестве результата. Я не понимаю, что вы имеете в виду под </tr>.   -  person Günter Zöchbauer    schedule 29.02.2016
comment
Я думаю, вам нужно сначала сгладить вложенную структуру JSON в коде.   -  person Günter Zöchbauer    schedule 29.02.2016
comment
Это было бы очень грустно. Мне пришлось бы создавать избыточные данные и синхронизировать их :-(   -  person Witek    schedule 29.02.2016
comment
Angular позволяет создавать собственные структурные директивы, такие как ngIf, ngFor. Вы можете создать вариант ngFor, который делает это ;-)   -  person Günter Zöchbauer    schedule 29.02.2016
comment
Также есть элемент tbody, идеально подходящий для этого случая.   -  person Akxe    schedule 29.09.2016


Ответы (7)


Вы можете использовать синтаксис шаблона ngFor на groups и обычный синтаксис внутри него для фактических строк, таких как:

<table>
  <template let-group ngFor [ngForOf]="groups">
    <tr *ngFor="let row of group.items">{{row}}</tr>
  </template>
</table>

Проверьте этот планк

person Abdulrahman Alsoghayer    schedule 11.05.2016

Вот базовый подход - его, конечно, можно улучшить - того, что я понял как ваше требование.

Это отобразит 2 столбца, один с именем группы и один со списком элементов, связанных с группой.

Хитрость заключается в том, чтобы просто включить список в ячейку элементов.

<table>
  <thead>
    <th>Groups Name</th>
    <th>Groups Items</th>
  </thead>
  <tbody>
    <tr *ngFor="let group of groups">
      <td>{{group.name}}</td>
      <td>
        <ul>
          <li *ngFor="let item of group.items">{{item}}</li>
        </ul>
      </td>
    </tr>
  </tbody>
</table>
person avi.elkharrat    schedule 19.12.2017
comment
Спасибо за отсутствующую цитату в конце групп :) - person avi.elkharrat; 30.01.2018
comment
Как раз то, что мне было нужно. Просто и понятно - person makoshichi; 24.04.2018

это не точный результат, который вы хотели, но, возможно, что-то вроде этого подойдет. Родительский ЦМП:

<table>
  <item *ngFor="#i of items" [data]="i"></item>
</table>

Детский ЦМП

import {Component} from 'angular2/core';

@Component({
  selector: `item`,
  inputs: ['data'],
  template: `
    <tr><td>{{data.name}}</td></tr>
    <tr *ngFor="#i of data.items">
      <td><h1>{{i}}</h1></td>
    </tr>
  `
})
export default class Item {


}
person kit    schedule 29.02.2016

Попробуй это. Область действия локальных переменных определяется директивой "template".

<table>
  <template ngFor let-group="$implicit" [ngForOf]="groups">
    <tr>
      <td>
        <h2>{{group.name}}</h2>
      </td>
    </tr>
    <tr *ngFor="let item of group.items">
                <td>{{item}}</td>
            </tr>
  </template>
</table>
person yitzhak    schedule 11.05.2016

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

getItemsForDisplay():String[] {
 return [].concat.apply([],this.groups.map(group => group.items));
};

<tr *ngFor="let item of getItemsForDisplay()"><td>{{item}}</td></tr>

Это позволит вам сохранить вашу презентацию свободной от специальной логики. Это также позволяет вам использовать ваш источник данных «напрямую».

person Malfus    schedule 30.09.2016

Это сработало для меня.

<table>
  <tr>
    <td *ngFor="#group of groups">
       <h1>{{group.name}}</h1>
   </td>
  </tr>
</table>
person neticous    schedule 08.02.2017
comment
Это сработало для меня ‹td *ngFor=let header of blueHeaders style=width:100px; выравнивание текста: по центру; цвет фона: #366092›‹/td› - person Ziggler; 22.11.2017

person    schedule
comment
Пожалуйста, добавьте объяснение к вашему ответу, например, как это работает и решает проблему. - person Our Man in Bananas; 13.08.2020