Baris tabel Angular2 sebagai komponen

99

Saya bereksperimen dengan angular2 2.0.0-beta.0

Saya memiliki tabel dan konten garis dihasilkan oleh angular2 dengan cara ini:

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

Sekarang ini bekerja dan saya ingin merangkum konten ke dalam "baris tabel" komponen.

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

Dan di dalam komponen, template memiliki konten <tr> <td>.

Tapi sekarang meja itu tidak berfungsi lagi. Artinya, konten tersebut tidak lagi ditampilkan dalam kolom. Di browser, inspektur menunjukkan kepada saya bahwa elemen DOM terlihat seperti ini:

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

Bagaimana saya bisa membuat ini bekerja?

fbenoit.dll
sumber

Jawaban:

111

gunakan elemen tabel yang ada sebagai pemilih

Elemen tabel tidak mengizinkan <table-line>elemen sebagai anak-anak dan browser hanya menghapusnya saat ditemukan. Anda dapat membungkusnya dalam sebuah komponen dan tetap menggunakan <tr>tag yang diizinkan . Gunakan saja "tr"sebagai pemilih.

menggunakan <template>

<template>seharusnya diizinkan juga, tetapi belum berfungsi di semua browser. Angular2 sebenarnya tidak pernah menambahkan <template>elemen ke DOM, tetapi hanya memprosesnya secara internal, oleh karena itu ini dapat digunakan di semua browser dengan Angular2 juga.

Atribut selektor

Cara lain adalah dengan menggunakan penyeleksi atribut

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

untuk digunakan seperti

<tr my-tr>
Günter Zöchbauer
sumber
Jadi saya akan membuat TableItemComponent saya dengan selector = 'tr'. Tetapi bagaimana menggunakan 'tr' di tempat lain untuk masalah yang berbeda?
fbenoit
6
Jika komponen induk menyertakan trtag kustom Anda, itu akan digunakan, jika tidak, perilaku browser default-nya akan terjadi. Anda juga dapat menambahkan atribut atau kelas ke pemilih komponen Anda seperti <tr line-item>dengan pemilih komponen "tr[line-item] "atau <tr class="line-item">dengan pemilih komponen tr.line-item. Dengan cara ini Anda memiliki kendali penuh. Saya belum mencoba semua ini sendiri di Angular2, tapi saya cukup yakin ini berhasil.
Günter Zöchbauer
5
Apakah ada kelemahan nyata untuk ini? Ini berfungsi dengan baik, namun pengaturan default untuk tslintmengarahkan saya ke panduan gaya yang merekomendasikan untuk tidak melakukannya. Aku tidak suka mematikan direkomendasikan linting aturan, tetapi sejauh yang saya tahu, tampaknya aturan cukup sewenang-wenang gaya dan tidak dapat dihindari dalam beberapa situasi (seperti masalah OP)
Rob
1
Saya cukup yakin tidak ada kekurangannya, kecuali bahwa pemilih elemen jauh lebih umum dan karena itu harus menjadi default. Jika ada kasus yang valid seperti elemen tabel atau <li>atau serupa, saya tidak melihat alasan mengapa tidak menggunakannya.
Günter Zöchbauer
2
Membuat pemilih komponen saya menggunakan tr [item baris] berfungsi dan sesuai dengan aturan panduan Gaya Sudut STYLE 05-03 yang dikeluhkan tslint.
CM
31

Saya menemukan contoh ini sangat berguna tetapi tidak berfungsi di versi 2,2.3, jadi setelah banyak garukan kepala membuatnya berfungsi kembali dengan beberapa perubahan kecil.

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(); }
}
DudeOfDoom
sumber
1
Jawaban yang bagus. Saya hanya perlu menambahkan MyTrComponentke app.module.tsdan berfungsi dengan baik.
Tito Leiva
26

Berikut contoh penggunaan komponen dengan selektor atribut:

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

Keluaran:

1   2   3
11  12  13

Tentu saja template di MyTrComponent akan lebih banyak terlibat, tetapi Anda mengerti.

Old (beta.0) plunker .

Mark Rajcok
sumber
Apakah mungkin untuk merender komponen tanpa tag root? Sesuatu seperti <! - / ko -> di Knockout.js.
Ssss
@PashaPasha, lihat stackoverflow.com/questions/34280475/…
Mark Rajcok
14
Ini tidak bekerja sama sekali (dicoba dengan sudut 2.3). Kesalahan dilempar:Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'myTr' since it isn't a known property of 'tr'.
Vukasin
Untuk membuatnya bekerja, Anda perlu menambahkan [] pada Selector. Jangan lupakan itu.
AFetter
6

Menambahkan 'display: konten' ke gaya komponen berhasil bagi saya.

CSS:

.table-line {
    display: contents;
}

HTML:

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

Mengapa ini berhasil?

Saat membuat instance komponen, angular (setelah dikompilasi) membungkus konten komponen di DOM sebagai berikut:

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

Namun agar tabel dapat ditampilkan dengan benar, trtag tidak dapat dibungkus oleh apa pun.

Jadi, kami menambahkan display: contents, ke elemen baru ini. Seperti yang saya pahami, apa yang dilakukannya adalah memberi tahu penjelajah bahwa tag ini tidak boleh dirender, dan menampilkan konten dalam seolah-olah tidak ada pembungkus. Jadi, sementara tag masih ada, itu tidak mempengaruhi secara visual ke tabel, dan trtag diperlakukan seolah-olah mereka adalah turunan langsung dari tabletag.

Jika Anda ingin menyelidiki lebih lanjut tentang cara kerja konten: https://bitsofco.de/how-display-contents-works/

Ruben Negredo
sumber
1
Jika memungkinkan, berikan penjelasan tambahan, bukan hanya kode. Jawaban semacam itu cenderung lebih berguna karena membantu anggota komunitas dan terutama pengembang baru lebih memahami alasan solusi, dan dapat membantu mencegah kebutuhan untuk menjawab pertanyaan lanjutan.
Rajan
Hai @Rajan, terima kasih atas tipnya. Saya baru saja menemukan cara contentskerjanya, jadi saya tidak ingin meletakkan informasi di sana berdasarkan asumsi yang salah ... Saya menambahkan penjelasan sesuai yang saya pahami, tetapi jika seseorang melihat ada kesalahan di dalamnya, silakan tunjukkan ^ ^. Saya juga menambahkan tautan sehingga orang dapat menyelidiki lebih lanjut ... Satu hal yang saya perhatikan, sementara dikatakan bahwa ini tidak berfungsi di IE11, saya mencobanya di IE 11.657.18362.0 dan berfungsi dengan baik (tetapi, karena saya menggunakan sudut, mungkin ada polyfill di suatu tempat, jadi saya tidak akan menjaminnya 100% di lingkungan lain)
Ruben Negredo
Jawaban yang sangat bagus. IMO ini harus diterima.
adamsfamily
-3

coba ini

@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{}
Matsteel
sumber