Righe della tabella Angular2 come componente


99

Sto sperimentando angular2 2.0.0-beta.0

Ho una tabella e il contenuto della riga viene generato da angular2 in questo modo:

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

Ora funziona e voglio incapsulare il contenuto in un componente "table-line".

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

E nel componente, il modello ha il contenuto <tr> <td>.

Ma ora il tavolo non funziona più. Ciò significa che il contenuto non viene più mostrato nelle colonne. Nel browser, l'ispettore mi mostra che gli elementi DOM hanno questo aspetto:

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

Come posso farlo funzionare?

Risposte:


111

usa gli elementi della tabella esistenti come selettore

L'elemento table non consente gli <table-line>elementi come figli e il browser li rimuove solo quando li trova. Puoi racchiuderlo in un componente e continuare a utilizzare il <tr>tag consentito . Basta usare "tr"come selettore.

utilizzando <template>

<template>dovrebbe essere consentito, ma non funziona ancora in tutti i browser. Angular2 in realtà non aggiunge mai un <template>elemento al DOM, ma li elabora solo internamente, quindi questo può essere utilizzato anche in tutti i browser con Angular2.

Selettori di attributi

Un altro modo è usare i selettori di attributi

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

da usare come

<tr my-tr>

Quindi creerei il mio TableItemComponent con un selettore = 'tr'. Ma come si può usare 'tr' in altri posti per problemi diversi?
fbenoit

6
Se il componente principale include il trtag personalizzato , verrà utilizzato, altrimenti si verificherà il comportamento del browser predefinito. Puoi anche aggiungere attributi o classi al tuo selettore di componenti come <tr line-item>con un selettore di componenti "tr[line-item] "o <tr class="line-item">con un selettore di componenti tr.line-item. In questo modo hai il pieno controllo. Non ho ancora provato nulla di tutto questo in Angular2, ma sono abbastanza sicuro che funzioni.
Günter Zöchbauer

5
C'è qualche vero svantaggio in questo? Funziona bene, tuttavia le impostazioni predefinite per tslintme diretto alla guida di stile raccomandare contro questo. Non mi piace disattivare le regole di linting consigliate, ma per quanto ne so, sembra una regola di stile abbastanza arbitraria e inevitabile in alcune situazioni (come il problema di OP)
Rob

1
Sono abbastanza sicuro che non ci siano inconvenienti, tranne che i selettori di elementi sono molto più comuni e quindi dovrebbero essere i valori predefiniti. Se esiste un caso valido come elementi di tabella <li>o simili, non vedo alcun motivo per non usarlo.
Günter Zöchbauer

2
Fare in modo che il mio selettore di componenti utilizzi tr [elemento pubblicitario] ha funzionato ed è conforme alla regola della guida di stile angolare STILE 05-03 contro cui tslint si lamenta.
CM

31

Ho trovato l'esempio molto utile ma non ha funzionato nella build 2.2.3, quindi dopo aver grattato la testa molto lo ha fatto funzionare di nuovo con alcune piccole modifiche.

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
Bella risposta. Ho solo dovuto aggiungere il MyTrComponenta app.module.tse funziona bene.
Tito Leiva

26

Ecco un esempio di utilizzo di un componente con un selettore di attributi:

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

Produzione:

1   2   3
11  12  13

Ovviamente il modello in MyTrComponent sarebbe più coinvolto, ma hai capito.

Vecchio (beta.0) plunker .


È possibile eseguire il rendering del componente ng senza tag root? Qualcosa come <! - / ko -> in Knockout.js.
Ssss


14
Questo non funziona affatto (provato con angular 2.3). Errore generato:Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'myTr' since it isn't a known property of 'tr'.
Vukasin

Per farlo funzionare è necessario aggiungere [] su Selector. Non dimenticarlo.
Meglio l'

6

L'aggiunta di "display: contents" allo stile del componente ha funzionato per me.

CSS:

.table-line {
    display: contents;
}

HTML:

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

Perché funziona?

Quando si istanzia un componente, angular (dopo la compilazione) avvolge il contenuto del componente nel DOM come segue:

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

Ma affinché la tabella trvenga visualizzata correttamente, i tag non possono essere racchiusi da nulla.

Quindi, aggiungiamo display: contents, a questo nuovo elemento. Da quanto ho capito, ciò che fa è dire all'esploratore che questo tag non deve essere visualizzato e visualizzare il contenuto interno come se non ci fosse alcun avvolgimento. Quindi, mentre il tag esiste ancora, non influisce visivamente sulla tabella e i trtag vengono trattati come se fossero figli diretti del tabletag.

Se desideri approfondire il funzionamento dei contenuti: https://bitsofco.de/how-display-contents-works/


1
Quando possibile, sforzati di fornire spiegazioni aggiuntive anziché solo codice. Tali risposte tendono ad essere più utili in quanto aiutano i membri della comunità e in particolare i nuovi sviluppatori a comprendere meglio il ragionamento della soluzione e possono aiutare a prevenire la necessità di rispondere alle domande di follow-up.
Rajan

Ciao @ Rajan, grazie per il suggerimento. Ho appena scoperto come contentsfunziona, quindi non volevo inserire informazioni basate su false supposizioni ... Ho aggiunto la spiegazione per come la capisco, ma se qualcuno nota che c'è un errore non esitate a segnalarlo ^ ^. Ho anche aggiunto un collegamento in modo che le persone possano indagare ulteriormente ... Una cosa che ho notato, mentre dice che questo non funziona su IE11, l'ho provato su IE 11.657.18362.0 e ha funzionato bene (ma, dato che sono utilizzando angular, potrebbe esserci un polyfill da qualche parte, quindi non lo garantisco al 100% su altri ambienti)
Ruben Negredo

Risposta molto buona. IMO questo dovrebbe essere accettato.
adamsfamily

-3

prova questo

@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{}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.