7

I have a lot of html tables that share the same 15 columns along with custom columns that are specific for each table. I would like to create these common 15 columns as a component that takes in a set of data and shows up as the 15 td's without a wrapper. I can't figure out how to create an Angular component that doesn't show the wrapper tag in the DOM and allows me to pass in input. Below is kind of what I'd like to do:

<tr *ngFor="let item of items">
  <td>Column 1</td>
  <my-common-columns [data]="item"></my-common-columns>
  <td>Another column</td>
</tr>

Unfortunately with the above code, <my-common-columns> tag shows up in the rendered DOM, which messes up the table. I can only have td's under the tr tag.

I also tried <ng-container *ngComponentOutlet="myCommonColumns"> since ng-container's don't show up in the DOM, but I can't figure out how to pass data into it.

4 Answers 4

5
import { Component, TemplateRef, ViewChild } from '@angular/core';

@Component({
  selector: 'my-common-columns',
  template: `<ng-template let-item>
  <td>inner item1:{{item}}</td>
  <td>inner item2:{{item}}</td>
  </ng-template>`
})
export class CommonComponent {
  @ViewChild(TemplateRef) template: TemplateRef<any>;
}


@Component({
  selector: 'my-app',
  template: `
  <table>
    <tr *ngFor="let item of data">
      <td>first</td>
      <ng-template [ngTemplateOutlet]="common.template"
                 [ngTemplateOutletContext]="{$implicit: item}">
      </ng-template>
      <td>last</td>
    </tr>
  </table>
<my-common-columns #common></my-common-columns>
  `
})
export class AppComponent  {
  data = [1, 2, 3, 4, 5];
}

live example

result:

result

ngComponentOutlet will show tag in HTML too. Either, you should use abstraction to display tables for complex problems.

Sign up to request clarification or add additional context in comments.

1 Comment

Wow that's really clever. I think that does solve it. Thanks! I do feel like Angular should make this easier to do with a way to not render the parent tag, but this does the trick I guess.
1

Depending on your data structure you could probably do something like:

<td *ngFor="let col of item">{{ col }}</td>

1 Comment

I should have said that there's a lot of formatting differences between those included cells. Some of those <td>'s that are shared among tables have various styles or content that isn't just a simple {{col}}
0

You have to use your component as a attribute. So put it to <td my-common-column></td> and in your component change selector: [my-common-column]. These [ ] brackets allows you to use component as attribute.

2 Comments

But I need a set of 15 <td> cells. I want to just have 1 component that injects all 15 cells.
Then put *ngFor above or inside the component
-1

Why don't you use the code below?

<tr *ngFor="let item of items">
  <td>Column 1</td>
  <td> {{ item }}</td>
  <td>Another column</td>
</tr>

1 Comment

There's a large number of <td> cells I want to include.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.