Chux
Chux

Reputation: 1227

ngFor in a tr not working as expected in angular2

I'm playing around with angular 2 (first day;)).

I'm using a component that displays a tr, and the another that will repeat tr's inside of it.

<h3>Sensor list</h3>
<a (click)="refreshSensors()" class="btn btn-primary">Escanear Sensores</a>

<table class="table">
    <thead>
        <tr>
            <th>Sensor</th>
            <th>Description</th>
        </tr>
    </thead>
    <sensor-list [sensors]="sensors"></sensor-list>
</table>

and then, in sensor list:

<h3>Sensor list</h3>
<a (click)="refreshSensors()" class="btn btn-primary">Escanear Sensores</a>

<table class="table">
    <thead>
        <tr>
            <th>Sensor</th>
            <th>Description</th>
        </tr>
    </thead>
    <sensor-list [sensors]="sensors"></sensor-list>
</table>

While ngFor is repeating the tr's propertly, i'm getting a tag inside my html that makes the table not displaying as it should:

td's not displaying as expected

    <table class="table">
    <thead>
        <tr>
            <th>Sensor</th>
            <th>Description</th>
        </tr>
    </thead>
    <sensor-list><tbody><!--template bindings={}--><tr>
    <td>R2D2</td>
    <td>Description of r2d2</td>
</tr><tr>
    <td>C3PO</td>
    <td>Description of c3po</td>
</tr></tbody></sensor-list>
</table>

Do I have to specify the tag i want to display in the component? what is the correct way of doing this in angular?

Upvotes: 1

Views: 5829

Answers (4)

Tomasz Grabowski
Tomasz Grabowski

Reputation: 21

Do something alike

PARENT COMPONENT TEMPLATE

<tr tool *ngFor='let tool of tools' [_tool]='tool'>

CHILD COMPONENT

import {Component, Input, OnChanges} from '@angular/core'
import {ITool} from '../../app/common/interfaces/ITool'

@Component({
    selector: '[tool]',
    templateUrl: 'app/toolslist/tool.template.html',
    styleUrls: ['app/toolslist/tool.style.css'],
})

export class ToolComponent implements OnChanges{
    @Input() _tool: ITool; 

    constructor() {

    }

    ngOnChanges():void{
        console.log(this._tool);
    };
}

Upvotes: 0

Wojciech Kwiatek
Wojciech Kwiatek

Reputation: 6802

Components inside HTML table

I want to expand on that a little bit more. This is tricky one. Probably most of the people starting with dynamically rendered tables encountered that.

Here is the code you've got (cleaned):

import { Component } from '@angular/core';

@Component({
  selector: 'table-body',
  template: `
    <tr>
      <td>Cell 1</td>
      <td>Cell 2</td>
    </tr>
  `
})
class TableBodyComponent {}

@Component({
  selector: 'sg-app',
  template: `
    <table>
      <thead>
        <tr>
          <th>Header 1</th>
          <th>Header 2</th>
        </tr>
      </thead>
      <table-body></table-body>
    </table>
  `,
  directives: [TableBodyComponent]
})
export class AppComponent {}

What Angular renders is the following: Angular 2 Table Rendering

And it's not a valid HTML (ref: MDN Table). This way view is broken and unpredictable.

Components on table rows

However you still can add components or directives (as an attribute) to the <tr> tag:

import { Component } from '@angular/core';

@Component({
  selector: '[table-row]',
  template: `
    <td>Cell 1</td>
    <td>Cell 2</td>
  `
})
class TableBodyComponent {}

@Component({
  selector: 'sg-app',
  template: `
    <table>
      <thead>
        <tr>
          <th>Header 1</th>
          <th>Header 2</th>
        </tr>
      </thead>
      <tbody>
         <tr table-row></tr>      
      </tbody>
    </table>
  `,
  directives: [TableBodyComponent]
})
export class AppComponent {}

This way you can also add *ngFor to the <tr>

Upvotes: 3

Hitesh Balar
Hitesh Balar

Reputation: 181

Your sensor-list component should be like this

Is your sensor component like this

import {Component, Input} from 'angular2/core';

@Component({
  selector: 'sensor-list',
  template: `
       <tbody>
          <tr *ngFor="let row of sensors">
            <td>{{row.sensor}}</td>
            <td>{{row.description}}</td>
          </tr>
       <tbody>
  `,
  providers: []
})
export class Sensor {
  @Input('sensors') type: any;

  constructor() {}
}

And your home component's template should be like this :

<sensor-list [sensors]="sensors"></sensor-list>

Upvotes: 0

Maximilian Riegler
Maximilian Riegler

Reputation: 23506

Angular 2 always leaves the host tag in the DOM and only inserts the HTML from your template into this host tag. Since a list of tr tags isn't really a good use for a component, I would rethink your code design choice there. It would probably be better to put the whole table into a component.

Upvotes: -1

Related Questions