【问题标题】:Angular2 table rows as componentAngular2 表格行作为组件
【发布时间】:2016-04-06 00:10:21
【问题描述】:

我正在试验 angular2 2.0.0-beta.0

我有一个表格,行内容是由angular2这样生成的:

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

现在可以了,我想将内容封装到一个组件“table-line”中。

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

并且在组件中,模板有

的内容。

但现在这张桌子不再工作了。这意味着,内容不再显示在列中。 在浏览器中,检查器显示 DOM 元素如下所示:

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

我怎样才能做到这一点?

【问题讨论】:

    标签: angular


    【解决方案1】:

    使用现有的表格元素作为选择器

    table 元素不允许 &lt;table-line&gt; 元素作为子元素,浏览器会在找到它们时将其删除。您可以将其包装在一个组件中,并且仍然使用允许的&lt;tr&gt; 标签。只需使用 "tr" 作为选择器。

    使用&lt;template&gt;

    &lt;template&gt; 也应该被允许,但还不能在所有浏览器中工作。 Angular2 实际上从不向 DOM 添加 &lt;template&gt; 元素,而只是在内部处理它们,因此这也可以在所有带有 Angular2 的浏览器中使用。

    属性选择器

    另一种方法是使用属性选择器

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

    像这样使用

    <tr my-tr>
    

    【讨论】:

    • 如果父组件包含您自定义的tr 标签,它将被使用,否则将发生默认浏览器行为。您还可以将属性或类添加到组件选择器,例如 &lt;tr line-item&gt; 与组件选择器 "tr[line-item] "&lt;tr class="line-item"&gt; 与组件选择器 tr.line-item。这样您就可以完全控制。我自己还没有在 Angular2 中尝试过任何这些,但我很确定这可行。
    • 这有什么真正的缺点吗?它工作正常,但是tslint 的默认设置将我引导到style guide 推荐反对。我不喜欢关闭推荐的 linting 规则,但据我所知,这似乎是一个相当随意的风格规则,在某些情况下是不可避免的(例如 OP 的问题)
    • 我很确定没有缺点,除了元素选择器更常见,因此应该是默认值。如果有像表格元素或&lt;li&gt; 或类似的有效案例,我看不出有什么不使用它的理由。
    • 使我的组件选择器使用 tr[line-item] 工作并符合 tslint 抱怨的 Angular 样式指南规则 STYLE 05-03。
    • 这只是一个样式规则。如果使用它是一个错误,他们将完全删除对它的支持,而不是创建样式规则。您的用例正是它实际受支持的原因。只需禁用 linter 规则即可。
    【解决方案2】:

    我发现该示例非常有用,但它在 2,2.3 版本中不起作用,因此经过多次摸索后,它通过一些小改动使其再次起作用。

    import {Component, Input} from '@angular/core'
    
    @Component({
      selector: "[my-tr]",
      template: `<td *ngFor='let item of row'>{{item}}</td>`    
    })
    export class MyTrComponent {
      @Input("line") row:any;
    }
    
    @Component({
      selector: "my-app",
      template: `<h1>{{title}}</h1>
      <table>
        <tr  *ngFor="let line of data" my-tr [line]="line"></tr>
      </table>`
    
    })
    export class AppComponent {
    
      title = "Angular 2 - tr attribute selector!";
      data = [ [1,2,3], [11, 12, 13] ];
      constructor() { console.clear(); }
    }
    

    【讨论】:

    • 很好的答案。我只需将MyTrComponent 添加到app.module.ts 即可正常工作。
    【解决方案3】:

    这是一个使用带有属性选择器的组件的示例:

    import {Component, Input} from '@angular/core';
    @Component({
      selector: '[myTr]',
      template: `<td *ngFor="let item of row">{{item}}</td>`
    })
    export class MyTrComponent {
      @Input('myTr') row;
    }
    @Component({
      selector: 'my-app',
      template: `{{title}}
      <table>
        <tr *ngFor="let line of data" [myTr]="line"></tr>
      </table>
      `
    })
    export class AppComponent {
      title = "Angular 2 - tr attribute selector";
      data = [ [1,2,3], [11, 12, 13] ];
    }
    

    输出:

    1   2   3
    11  12  13
    

    当然,MyTrComponent 中的模板会涉及更多,但你明白了。

    旧版(beta.0)plunker

    【讨论】:

    • 是否可以在没有根标签的情况下渲染 ng 组件?类似 在 Knockout.js 中的东西。
    • 这根本不起作用(用 angular 2.3 试过)。抛出的错误:Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'myTr' since it isn't a known property of 'tr'.
    • 要使其工作,您需要在 Selector 上添加 [ ]。不要忘记这一点。
    【解决方案4】:

    为我的组件样式添加“显示:内容”。

    CSS:

    .table-line {
        display: contents;
    }
    

    HTML:

    <table>
        <table-line class="table-line" [data]="line">
        </table-line>
    </table>
    

    为什么会这样?

    在实例化组件时,angular(编译后)将组件的内容包装在 DOM 中,如下所示:

    <table>
        <table-line>
            <tr></tr>
        </table-line>
    </table>
    

    但是为了表格能够正常显示,tr标签不能被任何东西包裹。

    因此,我们将display: contents 添加到这个新元素中。据我了解,这样做是告诉资源管理器不应呈现此标签,并显示内部内容,就好像没有环绕一样。因此,虽然标签仍然存在,但它不会影响表格的视觉效果,并且tr 标签被视为table 标签的直接子标签。

    如果您想进一步了解内容的运作方式: https://bitsofco.de/how-display-contents-works/

    【讨论】:

    • 如果可能,请努力提供额外的解释,而不仅仅是代码。此类答案往往更有用,因为它们可以帮助社区成员,尤其是新开发人员更好地理解解决方案的推理,并有助于避免需要解决后续问题。
    • 嗨@Rajan,感谢您的提示。我刚刚发现contents 是如何工作的,所以我不想根据错误的假设把信息放在那里......我添加了我理解的解释,但如果有人注意到它有错误,请随时指出出来了^^。我还添加了一个链接,以便人们可以进一步调查......我注意到一件事,虽然它说这在 IE11 上不起作用,但我在 IE 11.657.18362.0 上尝试了它并且它运行良好(但是,因为我使用角度,某处可能有一个 polyfill,所以我不能保证它在其他环境中 100%)
    【解决方案5】:

    试试这个

    @Component({
        selecctor: 'parent-selector',
        template: '<table><body><tra></tra></body></table>'
        styles: 'tra{ display:table-row; box-sizing:inherit; }'
    })
    export class ParentComponent{
    }
    
    @Component({
        selecctor: 'parent-selector',
        template: '<td>Name</td>Date<td></td><td>Stackoverflow</td>'
    })
    export class ChildComponent{}
    

    【讨论】:

      猜你喜欢
      • 2019-11-16
      • 2017-06-19
      • 1970-01-01
      • 2016-08-13
      • 2018-03-07
      • 1970-01-01
      • 2017-07-09
      • 1970-01-01
      相关资源
      最近更新 更多