So, as I started to dig in to angular2, I figured I create a table listing persons. One component for creating the table (person-list
), and one for component for each person in the table (person-list-item
).
Easy peezy, right? With the below output I realised it was not that easy. As you can see, the table rows are not following the table structure.
By viewing the html in the inspector we can also see that the <person-list-item>
is ruining the table.
Is there a way to solve this problem, or should I just create the table rows in the <person-list>
element in order to not let the browser ruin the table? I guess this is an issue that applies to other cases where multiple components would ruin a certain DOM element.
app.component
import {PersonListComponent} from './person-list.component';
import {Component} from 'angular2/core';
let template=`
<person-list></person-list>
`;
@Component({
selector:'appz',
template:template,
providers:[PersonService],
directives:[PersonListComponent]
})
export class AppComponent {
public title;
constructor(private _personService: PersonService) {
this.title=_personService.getPersons();
}
}
person-list.component
import {Component} from 'angular2/core';
import {PersonListItemComponent} from './person-list-item.component';
import {Person} from './person';
let template=`
<h3>Persons</h3>
<table class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<person-list-item
[firstName]="'John'"
[lastName]="'Doe'"
[age]='44'>
</person-list-item>
<person-list-item
[firstName]="'Foo'"
[lastName]="'Bar'"
[age]='34'>
</person-list-item>
</tbody>
</table>
`;
@Component({
selector:'person-list',
template:template,
directives:[PersonListItemComponent],
inputs:['persons']
})
export class PersonListComponent {
public persons: Person[];
};
person-list-item.component
import {Component} from 'angular2/core';
let template=`
<tr>
<td>{{firstName}}</td>
<td>{{lastName}}</td>
<td>{{age}}</td>
</tr>
`;
@Component({
selector:'person-list-item',
template: template,
inputs:['firstName', 'lastName', 'age']
})
export class PersonListItemComponent {
public firstName;
public lastName;
public age;
}
Just use an attribute or class selector instead of the tag selector for your component
for example selector: 'tr[person-list-item]'
and use it like
<tr person-list-item>
or selector: 'tr[personListItem]'
and <tr personListItem>
Alternatively you can use other ways to build a table.
For example like shown in https://github.com/dart-lang/polymer-dart-patterns/blob/b3e8a306d05a9f3aae695a75ca5f4e3dccd64cf5/web/control_flow/using_template_repeat_with_a_table_row/my_element.html for a similar use case for Polymer where CSS is used to set div
to behave like a table
/tr
/td
<style>
.table {
display: table;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}
</style>
<div class="table">
<template is="dom-repeat" items="{{fruits}}" as="fruit">
<div class="row">
<div class="cell">{{fruit}}</div>
</div>
</template>
</div>
Unless PersonListItemComponent will someday be more complicated, I would dispense with that component and generate the rows in PersonListComponent using the <template>
form of NgFor, which allows for multiple elements to be repeated.
Note: as Günter Zöchbauer mentions in the comments below, some browsers currently do not support <template>
elements inside <table>
elements. So this approach may be a bit premature.
import {Component, Input} from 'angular2/core';
@Component({
selector: 'person-list',
template: `
<table>
<tbody>
<template ngFor #person [ngForOf]="people">
<tr>
<td>{{person.name}}
<td>{{person.age}}
</template>
</tbody>
</table>
`,
styles: ['td { border: 1px solid gray } ']
})
export class PersonListComponent {
@Input() people;
}
@Component({
selector: 'my-app',
template: `<person-list [people]="people"></person-list>`,
directives: [PersonListComponent]
})
export class AppComponent {
people = [ { name: 'Mark', age: "over 40" }, {name: 'cbass', age: "24?" }];
constructor() { console.clear(); }
}
plunker
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With