Angular2 ตารางแถวเป็นส่วนประกอบ


103

ฉันกำลังทดลองกับ 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>

และในองค์ประกอบแม่แบบมีเนื้อหา <tr> <td>

แต่ตอนนี้โต๊ะไม่ทำงานอีกแล้ว ซึ่งหมายความว่าเนื้อหาจะไม่แสดงในคอลัมน์อีกต่อไป ในเบราว์เซอร์ตัวตรวจสอบแสดงให้ฉันเห็นว่าองค์ประกอบ DOM มีลักษณะดังนี้:

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

ฉันจะทำงานนี้ได้อย่างไร?

คำตอบ:


114

ใช้องค์ประกอบตารางที่มีอยู่เป็นตัวเลือก

องค์ประกอบตารางไม่อนุญาตให้<table-line>องค์ประกอบเป็นเด็กและเบราว์เซอร์จะลบออกเมื่อพบ คุณสามารถรวมไว้ในองค์ประกอบและยังคงใช้<tr>แท็กที่อนุญาต เพียงใช้"tr"เป็นตัวเลือก

โดยใช้ <template>

<template>ควรได้รับอนุญาตเช่นกัน แต่ยังใช้ไม่ได้กับทุกเบราว์เซอร์ Angular2 ไม่เคยเพิ่ม<template>องค์ประกอบลงใน DOM แต่จะประมวลผลภายในเท่านั้นดังนั้นจึงสามารถใช้กับเบราว์เซอร์ทั้งหมดที่มี Angular2 ได้เช่นกัน

ตัวเลือกแอตทริบิวต์

อีกวิธีหนึ่งคือการใช้ตัวเลือกแอตทริบิวต์

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

ที่จะใช้เช่น

<tr my-tr>

ดังนั้นฉันจะสร้าง TableItemComponent ของฉันด้วยตัวเลือก = 'tr' แต่จะใช้ 'tr' ในที่อื่นสำหรับปัญหาที่แตกต่างกันได้อย่างไร?
fbenoit

6
หากองค์ประกอบหลักมีtrแท็กที่กำหนดเองของคุณระบบจะใช้มิฉะนั้นจะเกิดพฤติกรรมเริ่มต้นของเบราว์เซอร์ นอกจากนี้คุณยังสามารถเพิ่มแอตทริบิวต์หรือเรียนเพื่อเลือกส่วนประกอบของคุณเช่น<tr line-item>มีตัวเลือกองค์ประกอบ"tr[line-item] "หรือมีตัวเลือกส่วนประกอบ<tr class="line-item"> tr.line-itemวิธีนี้คุณสามารถควบคุมได้เต็มที่ ฉันยังไม่ได้ลองทำสิ่งนี้ด้วยตัวเองใน Angular2 แต่ฉันค่อนข้างมั่นใจว่ามันใช้ได้
GünterZöchbauer

5
มีข้อเสียเปรียบจริงหรือไม่? มันใช้งานได้ดีอย่างไรก็ตามการตั้งค่าเริ่มต้นสำหรับtslintนำฉันไปยังคำแนะนำสไตล์ที่แนะนำให้ใช้กับสิ่งนี้ ฉันไม่ชอบการปิดกฎการตัดขุยที่แนะนำ แต่เท่าที่ฉันสามารถบอกได้ดูเหมือนว่าเป็นกฎสไตล์ที่ค่อนข้างเป็นพลและหลีกเลี่ยงไม่ได้ในบางสถานการณ์ (เช่นปัญหาของ OP)
Rob

1
ฉันค่อนข้างแน่ใจว่าไม่มีข้อเสียใด ๆ ยกเว้นว่าตัวเลือกองค์ประกอบนั้นเป็นวิธีที่ใช้กันทั่วไปมากกว่าดังนั้นจึงควรเป็นค่าเริ่มต้น หากมีกรณีที่ถูกต้องเช่นองค์ประกอบตารางหรือ<li>หรือคล้ายกันฉันไม่เห็นเหตุผลใด ๆ ที่จะไม่ใช้มัน
GünterZöchbauer

2
การทำให้ตัวเลือกส่วนประกอบของฉันใช้ tr [line-item] ใช้งานได้และเป็นไปตามกฎคู่มือสไตล์เชิงมุม STYLE 05-03 ที่ tslint ร้องเรียน
CM

32

ฉันพบว่าตัวอย่างมีประโยชน์มาก แต่มันใช้ไม่ได้ในบิลด์ 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(); }
}

1
คำตอบที่ดี ฉันแค่ต้องเพิ่มMyTrComponentเข้าไปapp.module.tsและใช้งานได้ดี
Tito Leiva

26

นี่คือตัวอย่างการใช้ส่วนประกอบที่มีตัวเลือกแอตทริบิวต์:

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 โดยไม่มีแท็กรูท บางอย่างเช่น <! - / ko -> ใน Knockout.js
59


14
สิ่งนี้ใช้ไม่ได้เลย (ลองด้วย 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'.
Vukasin

เพื่อให้ใช้งานได้คุณต้องเพิ่ม [] บน Selector อย่าลืมสิ่งนั้น
AFetter

7

การเพิ่ม 'display: contents' ให้กับรูปแบบส่วนประกอบได้ผลสำหรับฉัน

CSS:

.table-line {
    display: contents;
}

HTML:

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

ทำไมถึงได้ผล

เมื่อสร้างคอมโพเนนต์เชิงมุม (หลังการคอมไพล์) จะรวมเนื้อหาของคอมโพเนนต์ใน DOM ดังนี้:

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

แต่เพื่อให้ตารางแสดงอย่างถูกต้องtrแท็กจะไม่สามารถพันด้วยอะไรก็ได้

ดังนั้นเราจึงเพิ่มdisplay: contentsองค์ประกอบใหม่นี้ ตามที่ฉันเข้าใจสิ่งนี้คือการบอกนักสำรวจว่าไม่ควรแสดงแท็กนี้และแสดงเนื้อหาด้านในราวกับว่าไม่มีการห่อหุ้ม ดังนั้นแม้ว่าแท็กจะยังคงมีอยู่ แต่แท็กจะไม่ส่งผลกระทบต่อตารางโดยทางสายตาและtrแท็กจะได้รับการปฏิบัติราวกับว่าเป็นแท็กย่อยโดยตรงของtableแท็ก

หากคุณต้องการตรวจสอบเพิ่มเติมเกี่ยวกับการทำงานของเนื้อหา: https://bitsofco.de/how-display-contents-works/


1
หากเป็นไปได้โปรดพยายามให้คำอธิบายเพิ่มเติมแทนการใช้รหัส คำตอบดังกล่าวมีแนวโน้มที่จะเป็นประโยชน์มากขึ้นเนื่องจากช่วยให้สมาชิกในชุมชนและโดยเฉพาะอย่างยิ่งนักพัฒนารายใหม่เข้าใจเหตุผลของโซลูชันได้ดีขึ้นและสามารถช่วยป้องกันไม่ให้ต้องตอบคำถามติดตามผล
Rajan

สวัสดี @Rajan ขอบคุณสำหรับคำแนะนำ ฉันเพิ่งค้นพบวิธีการcontentsทำงานดังนั้นฉันจึงไม่ต้องการใส่ข้อมูลที่ตั้งอยู่บนสมมติฐานที่ผิด ... ฉันเพิ่มคำอธิบายตามที่ฉันเข้าใจ แต่ถ้ามีคนสังเกตเห็นว่ามีข้อผิดพลาดโปรดชี้ให้เห็นได้ตามต้องการ ^ ^. ฉันยังเพิ่มลิงค์เพื่อให้ผู้คนสามารถตรวจสอบเพิ่มเติมได้ ... สิ่งหนึ่งที่ฉันสังเกตเห็นในขณะที่มันบอกว่ามันใช้ไม่ได้กับ IE11 ฉันลองใช้กับ IE 11.657.18362.0 และมันก็ใช้ได้ดี (แต่เนื่องจากฉัน ใช้เชิงมุมอาจมี polyfill อยู่ที่ไหนสักแห่งดังนั้นฉันจะไม่รับประกัน 100% ในสภาพแวดล้อมอื่น ๆ )
Ruben Negredo

ตอบได้ดีมาก. IMO ควรได้รับการยอมรับ
adamsfamily

แก้ไขง่ายๆ รักษารหัสให้สะอาด
bkbarton

-3

ลองดู

@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{}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.