Các hàng trong bảng Angular2 như một thành phần


99

Tôi đang thử nghiệm với angle2 2.0.0-beta.0

Tôi có một bảng và nội dung dòng được tạo bởi angle2 theo cách này:

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

Bây giờ điều này hoạt động và tôi muốn đóng gói nội dung vào một thành phần "dòng bảng".

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

Và trong thành phần, mẫu có nội dung <tr> <td>.

Nhưng bây giờ bàn không hoạt động nữa. Có nghĩa là, nội dung không còn được hiển thị trong các cột. Trong trình duyệt, trình kiểm tra cho tôi thấy rằng các phần tử DOM trông giống như sau:

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

Làm thế nào tôi có thể làm cho nó hoạt động?

Câu trả lời:


110

sử dụng các phần tử bảng hiện có làm bộ chọn

Phần tử bảng không cho phép <table-line>các phần tử là trẻ em và trình duyệt chỉ xóa chúng khi tìm thấy chúng. Bạn có thể bọc nó trong một thành phần và vẫn sử dụng <tr>thẻ được phép . Chỉ cần sử dụng "tr"như bộ chọn.

sử dụng <template>

<template>cũng nên được cho phép nhưng chưa hoạt động trên tất cả các trình duyệt. Angular2 thực sự không bao giờ thêm một <template>phần tử vào DOM, mà chỉ xử lý chúng trong nội bộ, do đó điều này cũng có thể được sử dụng trong tất cả các trình duyệt với Angular2.

Bộ chọn thuộc tính

Một cách khác là sử dụng bộ chọn thuộc tính

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

được sử dụng như

<tr my-tr>

Vì vậy, tôi sẽ tạo TableItemComponent của mình với selector = 'tr'. Nhưng làm thế nào có thể sử dụng 'tr' ở những nơi khác cho các vấn đề khác nhau?
fbenoit

6
Nếu thành phần chính bao gồm trthẻ tùy chỉnh của bạn, nó sẽ được sử dụng, nếu không thì đó là hoạt động trình duyệt mặc định diễn ra. Bạn cũng có thể thêm thuộc tính hoặc lớp vào bộ chọn thành phần của mình như <tr line-item>với bộ chọn thành phần "tr[line-item] "hoặc <tr class="line-item">với bộ chọn thành phần tr.line-item. Bằng cách này, bạn có toàn quyền kiểm soát. Tôi chưa thử bất kỳ điều này bản thân mình trong Angular2, nhưng tôi khá chắc chắn rằng điều này hoạt động.
Günter Zöchbauer

5
Có bất kỳ hạn chế thực sự cho điều này? Nó hoạt động tốt, tuy nhiên các cài đặt mặc định tslinthướng tôi đến hướng dẫn kiểu đề xuất chống lại điều này. Tôi không thích tắt các quy tắc kẻ viền được khuyến nghị, nhưng theo như tôi có thể nói, đó có vẻ là một quy tắc kiểu khá tùy tiện và không thể tránh khỏi trong một số tình huống (chẳng hạn như sự cố của OP)
Rob

1
Tôi khá chắc rằng không có nhược điểm, ngoại trừ việc các bộ chọn phần tử phổ biến hơn và do đó nên là mặc định. Nếu có một trường hợp hợp lệ như các phần tử bảng hoặc <li>hoặc tương tự, tôi không thấy lý do gì để không sử dụng nó.
Günter Zöchbauer,

2
Làm cho bộ chọn thành phần của tôi sử dụng tr [line-item] hoạt động và tuân thủ quy tắc hướng dẫn Kiểu Angular STYLE 05-03 mà tslint khiếu nại.
CM

30

Tôi thấy ví dụ rất hữu ích nhưng nó không hoạt động trong bản dựng 2.2.3, vì vậy sau nhiều lần gãi đầu, nó đã hoạt động trở lại với một vài thay đổi nhỏ.

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(); }
}

1
Câu trả lời chính xác. Tôi chỉ cần thêm MyTrComponentvào app.module.tsvà hoạt động tốt.
Tito Leiva

26

Dưới đây là một ví dụ sử dụng một thành phần có bộ chọn thuộc tính:

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] ];
}

Đầu ra:

1   2   3
11  12  13

Tất nhiên mẫu trong MyTrComponent sẽ được tham gia nhiều hơn, nhưng bạn sẽ có ý tưởng.

Cũ (beta.0) plunker .


Có thể hiển thị thành phần ng mà không có thẻ gốc không? Một cái gì đó giống như <! - / ko -> trong Knockout.js.
Ssss


14
Điều này hoàn toàn không hoạt động (đã thử với góc 2.3). Đã xảy ra lỗi:Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'myTr' since it isn't a known property of 'tr'.
Vukasin

Để làm cho nó hoạt động, bạn cần thêm [] vào Bộ chọn. Đừng quên điều đó.
AFetter

6

Việc thêm 'display: content' vào kiểu thành phần đã làm việc cho tôi.

CSS:

.table-line {
    display: contents;
}

HTML:

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

Tại sao điều này hoạt động?

Khi cài đặt một thành phần, angle (sau khi biên dịch) sẽ bao bọc nội dung của thành phần đó trong DOM như sau:

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

Nhưng để bảng hiển thị đúng cách, các trthẻ không thể được bọc bởi bất cứ thứ gì.

Vì vậy, chúng tôi thêm display: contents, vào phần tử mới này. Theo tôi hiểu, điều này làm là để cho người khám phá biết rằng thẻ này không nên được hiển thị và hiển thị nội dung bên trong như thể không có bao bọc xung quanh. Vì vậy, trong khi thẻ vẫn tồn tại, nó không ảnh hưởng trực quan đến bảng và các trthẻ được coi như thể chúng là con trực tiếp của tablethẻ.

Nếu bạn muốn điều tra thêm về cách hoạt động của nội dung: https://bitsofco.de/how-display-contents-works/


1
Khi có thể, hãy cố gắng cung cấp giải thích bổ sung thay vì chỉ mã. Những câu trả lời như vậy có xu hướng hữu ích hơn vì chúng giúp các thành viên của cộng đồng và đặc biệt là các nhà phát triển mới hiểu rõ hơn lý do của giải pháp và có thể giúp ngăn chặn nhu cầu giải quyết các câu hỏi tiếp theo.
Rajan

Xin chào @Rajan, cảm ơn vì mẹo. Tôi chỉ mới phát hiện ra cách contentshoạt động, vì vậy tôi không muốn đưa thông tin vào đó dựa trên các giả định sai lầm ... Tôi đã thêm giải thích khi tôi hiểu, nhưng nếu ai đó nhận thấy rằng có lỗi trên đó, vui lòng chỉ ra ^ ^. Tôi cũng đã thêm một liên kết để mọi người có thể điều tra thêm ... Một điều tôi nhận thấy, mặc dù nó nói rằng điều này không hoạt động trên IE11, tôi đã thử nó trên IE 11.657.18362.0 và nó hoạt động tốt (nhưng, vì tôi sử dụng góc cạnh, có thể có một polyfill ở đâu đó, vì vậy tôi sẽ không đảm bảo nó 100% trên các môi trường khác)
Ruben Negredo

Câu trả lời rất hay. IMO điều này nên được chấp nhận.
adamsfamily

-3

thử cái này

@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{}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.