0
votes

I need to render multi level data into a single flat table using Angular 2+. However, each section of the data is rendered by nested components. Since a component has its own tag, hence, its an invalid child of <tbody/>.

How do i render a component's content without rendering its own tag?

Below is a simplified example:

@Component({
  selector: 'app-table-section',
  template: '<tr><td><h3>{{heading}}</h3></td></tr>' + 
        '<tr *ngFor="let i in items">{{i}}<td></td></tr>',
})
export class TableSectionComponent {
    @Input() heading: string;
    @Input() items: string[];
}

Which is used by:

@Component({
  selector: 'app-date-table',
  template: '<table>' +
  '  <thead><tr><th>Item Name</th></tr></thead>' +
  '  <tbody>' +
  '    <app-table-section *ngFor="let section of data"' +
  '                       [heading]="section.name"' +
  '                       [items]="sectons.items"></app-table-section>' +
  '  </tbody>' +
  '</table>',
})
export class CustomerListItemComponent {
  data = [
    {name:'Foo', items:['1', '2']},
    {name:'Bar', items:['a', 'b', 'c']},
  ]

  constructor() {
  }
}

The above will render with the results of the for-loop occupying just 1 table cell instead of multiple rows like so:

<table>
  <thead><tr><th>Item Name</th></tr></thead>
  <tbody>
  <app-table-section>
    <tr>
      <td><h3>Foo</h3></td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
    </tr>
  </app-table-section>
  <app-table-section>
    <tr>
      <td><h3>Bar</h3></td>
    </tr>
    <tr>
      <td>a</td>
      <td>b</td>
      <td>c</td>
    </tr>
  </app-table-section>
  </tbody>
</table>

I hope to expect:

<table>
  <thead><tr><th>Item Name</th></tr></thead>
  <tbody>
    <tr>
      <td><h3>Foo</h3></td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
    </tr>
    <tr>
      <td><h3>Bar</h3></td>
    </tr>
    <tr>
      <td>a</td>
      <td>b</td>
      <td>c</td>
    </tr>
  </tbody>
</table>

I have read Angular2 : render a component without its wrapping tag and its accepted answer's discussion page but could not find what i needed for the above.

1
Here is another post on the same subject: stackoverflow.com/q/34556277/1009922.ConnorsFan
Appreciated, but not what i was looking for.A. K. Tolentino
If all else fails, this is a good workaround: stackoverflow.com/questions/42696738/…A. K. Tolentino

1 Answers

0
votes

I ended up using CSS 'sdisplay: contents. As of Sep 2018, major browsers (except Edge) now (at least partially) supports this. (Ref: caniuse.com)

:host {
  display: contents;
}