Wiersze tabeli Angular2 jako komponent

99

Eksperymentuję z angular2 2.0.0-beta.0

Mam tabelę, a zawartość linii jest generowana przez angular2 w ten sposób:

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

Teraz to działa i chcę zawrzeć zawartość w komponencie „wiersz tabeli”.

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

W komponencie szablon ma zawartość <tr> <td>.

Ale teraz stół już nie działa. Co oznacza, że ​​treść nie jest już wyświetlana w kolumnach. W przeglądarce inspektor pokazuje mi, że elementy DOM wyglądają tak:

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

Jak mogę to zrobić?

fbenoit
źródło

Odpowiedzi:

111

użyj istniejących elementów tabeli jako selektorów

Element table nie dopuszcza <table-line>elementów jako dzieci, a przeglądarka po prostu usuwa je, gdy je znajdzie. Możesz zawinąć go w komponent i nadal używać dozwolonego <tr>tagu. Po prostu użyj "tr"jako selektora.

za pomocą <template>

<template>powinno być również dozwolone, ale nie działa jeszcze we wszystkich przeglądarkach. Angular2 tak naprawdę nigdy nie dodaje <template>elementu do DOM, a jedynie przetwarza je wewnętrznie, dlatego może być używane we wszystkich przeglądarkach z Angular2.

Selektory atrybutów

Innym sposobem jest użycie selektorów atrybutów

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

do użytku jak

<tr my-tr>
Günter Zöchbauer
źródło
Więc utworzyłbym mój TableItemComponent z selector = 'tr'. Ale jak można używać „tr” w innych miejscach do różnych problemów?
fbenoit
6
Jeśli komponent nadrzędny zawiera Twój trtag niestandardowy , zostanie on użyty, w przeciwnym razie ma miejsce domyślne zachowanie przeglądarki. Możesz także dodawać atrybuty lub klasy do selektora komponentów, tak jak <tr line-item>selektor komponentów "tr[line-item] "lub <tr class="line-item">selektor komponentów tr.line-item. W ten sposób masz pełną kontrolę. Sam jeszcze nie próbowałem tego w Angular2, ale jestem prawie pewien, że to działa.
Günter Zöchbauer
5
Czy jest w tym jakaś prawdziwa wada? Działa dobrze, jednak domyślne ustawienia tslintkierują mnie do przewodnika stylów, który jest zalecany przeciwko temu. Nie podoba mi się wyłączanie zalecanych reguł lintingu, ale o ile wiem, wydaje mi się, że jest to zasada dość arbitralna i nieunikniona w niektórych sytuacjach (takich jak problem OP)
Rob
1
Jestem prawie pewien, że nie ma wady, z wyjątkiem tego, że selektory elementów są o wiele bardziej powszechne i dlatego powinny być domyślne. Jeśli istnieje ważny przypadek, taki jak elementy tabeli <li>lub podobne, nie widzę powodu, aby go nie używać.
Günter Zöchbauer
2
Wykorzystanie w selektorze komponentów tr [pozycja-pozycji] zadziałało i jest zgodne z regułą przewodnika Angular Style STYLE 05-03, na którą skarży się tslint.
CM
31

Uważam, że przykład jest bardzo przydatny, ale nie działał w kompilacji 2,2.3, więc po wielu drapaniach po głowie sprawił, że działał ponownie z kilkoma drobnymi zmianami.

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
źródło
1
Świetna odpowiedź. Po prostu musiałem dodać MyTrComponentdo app.module.tsi działa dobrze.
Tito Leiva,
26

Oto przykład użycia komponentu z selektorem atrybutu:

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

Wynik:

1   2   3
11  12  13

Oczywiście szablon w MyTrComponent byłby bardziej zaangażowany, ale masz pomysł.

Stary (beta.0) plunker .

Mark Rajcok
źródło
Czy można renderować komponent ng bez znacznika głównego? Coś w rodzaju <! - / ko -> w Knockout.js.
Ssss
@PashaPasha, patrz stackoverflow.com/questions/34280475/ ...
Mark Rajcok
14
To w ogóle nie działa (wypróbowano z kątowym 2.3). Zgłoszony błąd:Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'myTr' since it isn't a known property of 'tr'.
Vukasin
Aby to działało, musisz dodać [] na Selector. Nie zapomnij o tym.
AFter
6

Dodanie „display: content” do stylu komponentu wypracowało mi się.

CSS:

.table-line {
    display: contents;
}

HTML:

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

Dlaczego to działa?

Podczas instancji komponentu angular (po kompilacji) opakowuje zawartość komponentu w DOM w następujący sposób:

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

Ale aby tabela wyświetlała się poprawnie, trtagi nie mogą być niczym opakowane.

Więc dodajemy display: contentsdo tego nowego elementu. Jak rozumiem, ma to na celu poinformowanie eksploratora, że ​​ten tag nie powinien być renderowany, i wyświetlenie wewnętrznej zawartości tak, jakby nie było zawijania. Tak więc, gdy tag nadal istnieje, nie wpływa wizualnie na tabelę, a trtagi są traktowane tak, jakby były bezpośrednimi elementami tablepodrzędnymi tagu.

Jeśli chcesz dokładniej zbadać, jak działa zawartość: https://bitsofco.de/how-display-contents-works/

Ruben Negredo
źródło
1
Jeśli to możliwe, postaraj się podać dodatkowe wyjaśnienia zamiast tylko kodu. Takie odpowiedzi są zwykle bardziej przydatne, ponieważ pomagają członkom społeczności, a zwłaszcza nowym programistom, lepiej zrozumieć uzasadnienie rozwiązania i mogą pomóc w uniknięciu konieczności zadawania dodatkowych pytań.
Rajan
Cześć @Rajan, dzięki za wskazówkę. Właśnie odkryłem, jak contentsdziała, więc nie chciałem tam umieszczać informacji opartych na fałszywych założeniach ... Dodałem wyjaśnienie tak, jak je rozumiem, ale jeśli ktoś zauważy, że jest w nim błąd, to śmiało wskaż go ^ ^. Dodałem również link, aby ludzie mogli dalej badać ... Jedna rzecz, którą zauważyłem, chociaż mówi, że to nie działa na IE11, wypróbowałem to na IE 11.657.18362.0 i działało dobrze (ale ponieważ jestem używając kątownika, może gdzieś być polyfill, więc nie gwarantuję tego w 100% w innych środowiskach)
Ruben Negredo
Bardzo dobra odpowiedź. IMO należy to zaakceptować.
adamsfamily
-3

Spróbuj tego

@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
źródło