在Angular 2/4中显示特定数据
问题描述:
我有一个包含material_projects或project_services的项目api。我很困惑我将如何显示其中一个。如果我显示material_projects,那么我不能显示project_services。 project_services在api中必须是空的。在Angular 2/4中显示特定数据
getAllProjects() {
this.subscription = this.projectsService.getAll()
.subscribe(
(data:any) => {
this.projects = data.projects;
console.log(data);
},
error => {
console.log(error);
});
}
HTML
<div class="card-block" *ngFor="let project of projects | search : searchBOM">
<h2 class="proj-name">{{ project.name | titlecase }} </h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Material SKU</th>
<th>Material Name</th>
<th>Unit</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let innerItem of project.material_projects">
<td>{{innerItem.material.sku}}</td>
<td>{{innerItem.material.name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
</tbody>
</table>
</div>
答
如果你能保证约束,那么你可以简单地在两个列表进行迭代。
<tbody>
<tr *ngFor="let innerItem of project.material_projects">
<td>{{innerItem.material.sku}}</td>
<td>{{innerItem.material.name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
<tr *ngFor="let innerItem of project.project_services">
<td>{{innerItem.service.sku}}</td>
<td>{{innerItem.service.name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
</tbody>
作为替代方案,可以有条件地显示的一个或另一个:
<tbody>
<ng-container *ngIf="project.material_projects.length > 0; then #materialProjectsRows; else #projectServicesRows"></ng-container>
<ng-template #materialProjectsRows>
<tr *ngFor="let innerItem of project.material_projects">
<td>{{innerItem.material.sku}}</td>
<td>{{innerItem.material.name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
</ng-template>
<ng-template #projectServicesRows>
<tr *ngFor="let innerItem of project.projectServices">
<td>{{innerItem.service.sku}}</td>
<td>{{innerItem.service.name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
</ng-template>
</tbody>
或者,如果DTO的足够相似,则可以考虑共享多个视图逻辑:
<tbody>
<!-- You may want to perform the concatenation inside of the view model for additional clarity -->
<tr *ngFor="let innerItem of project.material_projects.concat(project.project_services)">
<td>{{(innerItem.material || innerItem.service).sku}}</td>
<td>{{(innerItem.material || innerItem.service).name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
</tbody>
编辑:
如果您想根据属性的存在使用不同的表格,那么您需要将您的*ngIf
语句移动到<table>
元素或直接子元素。根据您的意见,您可以尝试类似以下内容:
<div class="card-block" *ngFor="let project of projects | search : searchBOM">
<ng-container *ngIf="getProjectType(project)">
<h2 class="proj-name">{{ project.name | titlecase }}</h2>
<table *ngIf="getProjectType(project) === 'material'" class="table table-bordered table-striped">
<thead>
<tr>
<th>Material SKU</th>
<th>Material Name</th>
<th>Unit</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let innerItem of project.material_projects">
<td>{{innerItem.material.sku}}</td>
<td>{{innerItem.material.name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
</tbody>
</table>
<table *ngIf="getProjectType(project) === 'services'" class="table table-bordered table-striped">
<thead>
<tr>
<th>Project SKU</th>
<th>Project Name</th>
<th>Unit</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let innerItem of project.project_services">
<td>{{innerItem.project.sku}}</td>
<td>{{innerItem.project.name}}</td>
<td>{{innerItem.unit}}</td>
</tr>
</tbody>
</table>
</ng-container>
</div>
组件代码:
export class ProjectComponent {
...
public getProjectType(project: Project): 'material' | 'services' | null {
return project.material_projects.length > 0 ? 'material'
: project.project_services.length > 0 ? 'services'
: null;
}
...
}
有很多方法可以做到这一点。另一种选择是在模板中使用switch语句,或者添加额外的子(“虚拟”)组件来处理行为。
其实,material_projects和projects_services有不同的角色。如果他们既不是material_projects和project_services那么也不显示任何东西 –
如何做出3个条件,如没有material_projects或project_services,那么不显示该特定项目? –
@GraySingh,如果你需要添加第三个条件,那么你可以添加另一个'* ngIf'结构指令给父节点。查看修改。在Angular中有很多方法可以解决同样的问题,所以编写这个组件的方法有很多。您也可以考虑将事物(如项目显示)抽象为子组件。将内容分隔成更小的虚拟组件是'* ngFor'指令内容的常见模式。 –