gpt4 book ai didi

angular - 我可以拥有一个不呈现伪元素的组件吗?

转载 作者:太空狗 更新时间:2023-10-29 18:28:26 25 4
gpt4 key购买 nike

我正在尝试创建一组允许我呈现表格的组件,其中“用户”只需要提供:

  • 数据(二维数组)
  • 每列一个单元格模板

因此,理想情况下,您可以使用这些组件来呈现一个 3 列表,如下所示:

<app-table [data]='sampleData'>
<td>{{cell.toString().toUpperCase()}}</td>
<td class="myClass">{{cell}}</td>
<app-cell [cell]="cell"></app-cell>
</app-table>

...app-table 组件将呈现三个 app-column 组件每一行,并且神奇地将单元格值作为 cell 提供给每一列。然后组件的用户可以完全控制每一列的呈现方式 - 包括将哪些类应用于 td 标记等。

我在尝试实现这一目标时运气不佳。到目前为止我想出的最好的可以在 this StackBlitz 中看到,其中我有一个呈现 trapp-table 组件,它期望其内容为每一列包含一个 ng-template。标记不像上面的伪标记那样干净:

<app-table [data]='sampleData'>
<ng-template let-cell="cell"><td>{{cell.toString().toUpperCase()}}</td></ng-template>
<ng-template let-cell="cell"><td class="myClass">{{cell}}</td></ng-template>
<ng-template let-cell="cell"><td><app-cell [data]="cell"></app-cell></td></ng-template>
</app-table>

这有点难看,因为将数据向下传递到模板中需要所有额外的标记,但这不是最大的问题。

您会注意到最后一个“列”使用了一个 app-cell 组件,但该组件仍然包含在一个 td 标签中:

<ng-template let-cell="cell">
<td>
<app-cell [data]="cell"></app-cell>
</td>
</ng-template>

这不是我真正想要的:我希望 app-cell 组件自己提供 td 标签,否则它不能(例如)在该元素上设置类。

目前,app-cell 组件有一个 HostBinding 添加了一个类(“foo”),但是它被添加到 app-cell 元素本身,而不是需要它的 td 元素:

<td>
<app-cell class="foo">
<div>...</div>
</app-cell>
</td>

显而易见的事情是将 td 标签移动到 app-cell 组件中,但是如果我 do that ,那么呈现的 HTML 如下所示:

<app-cell class="foo">
<td>
<div>...</div>
</td>
</app-cell>

[好的,所以该类仍然应用在错误的地方,但是很容易看出如何将它向下移动到 td 标签。]

但是,位于 trtd 元素之间的额外伪元素让我担心 - 我使用的浏览器似乎并不介意,但我怀疑我的大部分 CSS 都会被它抛出,因为有些选择器期望 tdtr 的直接子元素。

有没有办法摆脱那个额外的伪元素?通常我可能会考虑使用指令,但在这里我看不到如何做到这一点,因为 app-cell 组件需要一个模板,而指令没有这些...

最佳答案

这些类型的组件是我最喜欢的。归根结底,假设您有这样的数据,您需要如下内容

carData = [{
model: 'Mercedes',
year: 2015,
km: 10000
}, {
model: 'Audi',
year: 2016,
km: 5000
}];

并且您希望按原样显示前两列,而对于最后一列您希望显示一些自定义模板。

<app-table [data]="carData">
<app-cell header="Model" field="model"></app-cell>
<app-cell header="Year" field="year"></app-cell>
<app-cell header="Km" field="km" styleClass="km-cell">
<ng-template custom-cell-body let-car>
{{car.km | number}} km
</ng-template>
</app-cell>
</app-table>

这是你可以做的,(我从 Angular Material 和 Primeng 中得到了这个技巧,效果很好)

您可以找到一个工作示例 here

首先为单元格的自定义正文模板定义一个指令。 (你也可以对标题做同样的事情)

@Directive({selector: '[custom-cell-body]'})
export class AppCellBodyTemplate {
constructor(public template: TemplateRef<any>) {}
}

然后让我们定义我们的 AppCellComponent

app-cell.component.ts

@Component({
selector: 'app-cell',
template: `<ng-content></ng-content>`
})
export class AppCellComponent {
@Input() header;
@Input() field;
@Input() styleClass;

@ContentChild(AppCellBodyTemplate) customBody: AppCellBodyTemplate;
}

让我们在 AppTableComponent 将它们粘在一起

app-table.component.ts

@Component({
selector: 'app-table',
templateUrl: './app-table.component.html'
})
export class AppTableComponent {
@Input() data: any[];

@ContentChildren(AppCellComponent) cells: QueryList<AppCellComponent>;
}

app-table.component.html

  <table>
<thead>
<tr>
<!-- loop through cells and create header part of the table -->
<ng-container *ngFor="let cell of cells">
<th>{{cell.header}}</th>
</ng-container>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of data">
<!-- loop through cells -->
<ng-container *ngFor="let cell of cells">
<td [ngClass]="cell.styleClass">
<!-- if cell has a custom body, render that -->
<ng-container *ngIf="cell.customBody; else defaultBody">
<ng-container *ngTemplateOutlet="cell.customBody.template;
context: {$implicit: row}">
</ng-container>
</ng-container>
<!-- else render default cell body -->
<ng-template #defaultBody>{{row[cell.field]}}</ng-template>
</td>
</ng-container>
</tr>
</tbody>
</table>

这里有一些需要说明的地方。

  • template: TemplateRef<any>AppCellBodyTemplate 内因为,我们将使用 custom-body-cellng-template一直以来,我们都可以获得其中定义的模板的引用。这template将在 *ngTemplateOutlet 内使用
  • @ContentChild(AppCellBodyTemplate) customBodyAppCellComponent 内就是检测是否有custom-body-cell定义为 ContentChild
  • @ContentChildren(AppCellComponent) cells: QueryList<AppCellComponent>是获取 cells 的实例(你做了类似的事情)。
  • context: {$implicit: row}就是把一些数据暴露给这个组件的消费者。 $implicit使您能够使用所需的任何模板变量检索此上下文。因为,我使用了 $implicit在这里,我能够做到这一点 <ng-template custom-cell-body let-car>否则,我将不得不定义我的 car像这样的变量 let-car="rowData"

关于angular - 我可以拥有一个不呈现伪元素的组件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53613070/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com