120

I am experimenting with angular2 2.0.0-beta.0

I have a table and the line content is generated by angular2 this way:

    <table>
        <tr *ngFor="#line of data">
            .... content ....
        </tr>
    </table>

Now this works and I want to encapsulate the content into a component "table-line".

    <table>
        <table-line *ngFor="#line of data" [data]="line">
        </table-line>
    </table>

And in the component, the template has the <tr><td> content.

But now the table does no more work. Which means, the content is no longer shown in columns. In the browser, the inspector shows me that the DOM elements look like this:

    <table>
        <table-line ...>
            <tbody>
                <tr> ....

How can I make this work?

hirse
  • 2,394
  • 1
  • 22
  • 24
fbenoit
  • 3,220
  • 6
  • 21
  • 32

5 Answers5

140

use existing table elements as selector

The table element doesn't allow <table-line> elements as children and the browser just removes them when it finds them. You can wrap it in a component and still use the allowed <tr> tag. Just use "tr" as selector.

using <template>

<template> should be allowed as well but doesn't yet work in all browsers. Angular2 actually never adds a <template> element to the DOM, but only processes them internally, therefore this can be used in all browsers with Angular2 as well.

Attribute selectors

Another way is to use attribute selectors

@Component({
  selector: '[my-tr]',
  ...
})

to be used like

<tr my-tr>
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • So I would create my TableItemComponent with a selector = 'tr'. But how can use 'tr' in other places for different issues? – fbenoit Jan 01 '16 at 13:24
  • 6
    If the parent component includes your custom `tr` tag it will be used, otherwise it's default browser behavior takes place. You can also add attributes or classes to your component selector like `` with a component selector `"tr[line-item] "` or `` with component selector `tr.line-item`. This way you have full control. I haven't tried any of this myself yet in Angular2, but I'm pretty sure this works. – Günter Zöchbauer Jan 01 '16 at 13:30
  • Anyone got this working ? I'm trying but without any success with angular 2.3. If any of you can point to working plunker it will be priceless. – Vukasin Jan 04 '17 at 08:58
  • That's pretty basic and should just work. Why don't you provide a Plunker that demonstrates your problem? – Günter Zöchbauer Jan 04 '17 at 09:00
  • 7
    Is there any real drawback to this? It works fine, however the default settings for `tslint` direct me to the [style guide](https://angular.io/docs/ts/latest/guide/style-guide.html#!#05-03) recommending *against* this. I dislike turning off recommended linting rules, but as far as I can tell, it seems a fairly arbitrarily style rule and unavoidable in some situations (such as OP's problem) – Rob May 31 '17 at 08:18
  • 1
    I'm pretty sure there is no drawback, except that element selectors are way more common and therefore should be the default. If there is a valid case like table elements or `
  • ` or similar, I don't see any reason why not to use it.
  • – Günter Zöchbauer May 31 '17 at 17:18
  • 4
    Making my component selector use tr[line-item] worked and conforms to Angular Style guide rule STYLE 05-03 that tslint complains against. – C.M. Jun 07 '17 at 16:25
  • 1
    It's just a style rule. If using that were a mistake, they would remove support for it entirely instead of creating a style rule. Your use case is exactly why it's actually supported. Just disable the linter rule. – Günter Zöchbauer Jun 07 '17 at 16:28
  • It may be obvious to many (even to me now), but I tripped over __not__ closing the element with the custom attribute. To be precise: Use `` instead of `` – bleistift2 Feb 29 '20 at 15:40
  • The `my-tr` in the closing part of the element is *not* necessary. The root cause has to be somewhere else. – Günter Zöchbauer Mar 01 '20 at 08:45