1

when i create separately components for table and thead and tbody dissembling in a parent page, the table totally breaks.

don't know how to fix it.

table component:

<table>
    <ng-content></ng-content>
</table> 

thead component:

<thead>
  <tr>
    <th>Someple header</th>
    <th>Someple header</th>
  </tr>
</thead>

tbody component:

<tbody>
  <tr>
    <td>sample data1</td>
    <td>sample data2</td>
  </tr>
</tbody>

when put togather:

<app-table>
  <app-thead></app-thead>
  <app-tbody></app-tbody>
</app-table>

But it breaks the table. all are arranged as inline element. How to fix it?

Live URL please resize window

3gwebtrain
  • 14,640
  • 25
  • 121
  • 247

2 Answers2

3

If you inspect the table element, you will see it is rendered like this

<table>
  <app-thead>...</app-thead>
  <app-tbody>...</app-tbody>
</table> 

This itself is not a valid HTML. You cannot have any other wrapper for tbody / thead other than table. This is why your table is breaking, it is excepting tbody but instead it gets app-tbody and doesn't know what to do with it. I'd suggest not creating separate components for body and head of an table, or if you really have to do it you can like this:

Solution: Using attribute selector

In your app-table, app-thead, and app-tbody components convert the selector to attribute selector.

@Component({
  selector: '[app-table]'
  ...
})

After you do it in all places, you will load your custom table like this:

<table app-table>
  <thead app-thead></thead>
  <tbody app-tbody></tbody>
</table>

Also make sure to remove <table>, <tbody>, and <thead> wrappers from your custom components.

StackBlitz

Dino
  • 7,779
  • 12
  • 46
  • 85
  • what is the workaround for this? In my app I have no of tables, I would like to save time here.. – 3gwebtrain Jul 18 '19 at 10:32
  • Hey, guys, maybe a different approach can be of use here. Take a look what @angular/component guys do at this specific part of their datepicker (look at the `mat-calendar-body` component - yeah, it's not just a directive, it brings in the body view to the component): https://github.com/angular/components/blob/master/src/material/datepicker/month-view.html – julianobrasil Jul 18 '19 at 10:36
  • @3gwebtrain Please check it again, I've updated with a better solution. Also provided the stackblitz – Dino Jul 18 '19 at 10:51
  • @Dino - it works, but how can i pass data to `attrb` components? – 3gwebtrain Jul 18 '19 at 10:53
  • Same way as you used to. With @Input – Dino Jul 18 '19 at 11:00
1

If I understand what you are trying to do, I think you just need to replace the html for your TableComponent, TheadComponent and TbodyComponent components with just a <ng-content></ng-content> tag. Then you would set the display property on the <app-table>, <app-thead> and <app-tbody> to table, table-header-group and table-row-group respectively by using the :host selector. The code would look like the following:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Component } from '@angular/core';


@Component({
  selector: 'app-table',
  template: `<ng-content></ng-content>`,
  styles: [`:host { display:table; }`]
})
export class TableComponent {}


@Component({
  selector: 'app-thead',
  template: `<ng-content></ng-content>`,
  styles: [`:host { display:table-header-group; }`]
})
export class TheadComponent {}


@Component({
  selector: 'app-tbody',
  template: `<ng-content></ng-content>`,
  styles: [`:host { display:table-row-group; }`]
})
export class TbodyComponent {}


@Component({
  selector: 'app-root',
  template: `
      <app-table>
        <app-thead>Thead</app-thead>
        <app-tbody>Tbody</app-tbody>
      </app-table>
  `
})
export class AppComponent {}


@NgModule({
  declarations: [
    AppComponent, 
    TableComponent, 
    TheadComponent,
    TbodyComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

The code will then output as follows:

<app-table>
  <app-thead>Thead</app-thead>
  <app-tbody>Tbody</app-tbody>
</app-table>
Taurayi
  • 3,209
  • 2
  • 17
  • 15