Javascript Angular 5 NgFor-通过元素循环并检测已渲染的元素

Javascript Angular 5 NgFor-通过元素循环并检测已渲染的元素,javascript,angular,html,typescript,multidimensional-array,Javascript,Angular,Html,Typescript,Multidimensional Array,我已经创建了一个红灯,根据从数据库传递的值显示(红色、黄色、绿色)圆圈 目前,我正在使用颜色显示报告的状态*如果数组中只有一个对象,NgFor循环可以很好地将颜色放置在它们所属的位置。如果数据中没有报表ID(报表),则会出现一个“绿色”圆圈,这是它应该出现的方式。一次只能显示3种颜色,不能重复 问题是,如果值数组中存在第二个对象,则循环将忽略以前的值,并显示一个绿色圆圈,在该圆圈中应忽略该值,因为该reportId已存在一个值。如前所述,如果“值”数组中只有1个对象,它工作正常,绿色圆圈被应用并

我已经创建了一个红灯,根据从数据库传递的值显示(红色、黄色、绿色)圆圈

目前,我正在使用颜色显示报告的状态*如果数组中只有一个对象,NgFor循环可以很好地将颜色放置在它们所属的位置。如果数据中没有报表ID(报表),则会出现一个“绿色”圆圈,这是它应该出现的方式。一次只能显示3种颜色,不能重复

问题是,如果值数组中存在第二个对象,则循环将忽略以前的值,并显示一个绿色圆圈,在该圆圈中应忽略该值,因为该reportId已存在一个值。如前所述,如果“值”数组中只有1个对象,它工作正常,绿色圆圈被应用并放置在不存在的reportID的右侧位置,但是当有多个对象/报告列表时,它会给我第二行红绿灯,忽略第一次迭代中的设置值。实际上,它会将以前的reportID视为不存在,并放置一个绿色圆圈

有没有办法解决这个问题?我研究了异步管道,但没有100%确定如何在这个场景中应用它

数据如下所示:

{ key: 'Profit Loss', 
  value: [{ yellow: 'Y', red: 'N', reportId: 2 }]
},
{ key: 'Actuals', 
  value: [{ yellow: 'N', red: 'Y', reportId: 2 },
          { yellow: 'Y', red: 'N', reportId: 1 }]
}
循环的结构是这样的

            <div *ngFor="let siteMap of reportRow; let i = index;" >
               {{ siteMap.key }}
            <div *ngFor="let pMap of siteMap.value; let xi = index;" >
                <!---Report 1---->
                <!--------------->
                <tr *ngIf="pMap.yellow === 'Y' && pMap.reportId === 1">
                  <td><span class="yellowcolor"></span> <b>Report 1 Yellow</b></td>
                </tr>
                <tr *ngIf="pMap.red === 'Y' && pMap.reportId === 1">
                  <td><span class="redcolor"></span> <b>Report 1 Red</b></td>
                </tr>
                <tr *ngIf="pMap.reportId !== 1">
                  <td><span  class="greencolor"></span><b>Report 1 Green</b></td>
                </tr>
                <!---Report 2---->
                <!--------------->
                <tr *ngIf="pMap.yellow === 'Y' && pMap.reportId === 2">
                  <td><span class="yellowcolor"></span> <b>Report 2 Yellow</b></td>
                </tr>
                <tr *ngIf="pMap.red === 'Y' && pMap.reportId === 2">
                  <td><span class="redcolor"></span> <b>Report 2 Red</b></td>
                </tr>
                <tr *ngIf="pMap.reportId !== 2">
                  <td><span  class="greencolor"></span> <b>Report 2 Green</b></td>
                </tr>
                <!---Report 3---->
                <!--------------->
                <tr *ngIf="pMap.yellow === 'Y' && pMap.reportId === 3">
                  <td><span class="yellowcolor"></span> <b>Report 3 Yellow</b></td>
                </tr>
                <tr *ngIf="pMap.red === 'Y' && pMap.reportId === 3">
                  <td><span class="redcolor"></span> <b>Report 3 Red</b></td>
                </tr>
                <tr *ngIf="pMap.reportId !== 3">
                  <td><span  class="greencolor"></span> <b>Report 3 Green</b></td>
                </tr>
            </div>

{{siteMap.key}
报告1黄色
报告1红色
报告1绿色
报告2黄色
报告2红色
报告2绿色
报告3黄色
报告3红色
报告3绿色

您有多种解决方案,但我要做的是将复杂部分移到javascript:

渲染前对数组进行排序和填充:

ngOnInit() {

    let rawData = this.myService.get();

    for (let siteMap of rawData) {
        siteMap.value.sort(this.compare);
    }
    this.fillEmptyData(rawData);
    this.reportRow = rawData;
}

private compare(a,b) {
  if (a.reportId < b.reportId)
    return -1;
  if (a.reportId > b.reportId)
    return 1;
  return 0;
}

private fillEmptyData(dataToFill) {
    for (let column of dataToFill) {
        if (!column.value) {
            column.value = [];
        }
        for (let i = 0; i < 3; i++) {
            if (!column.value[i] || column.value[i].reportId !== (i + 1)) {
                // column.value[i] does not contain the expected reportId
                let emptyItem = {
                    reportId: i + 1,
                    reportName: 'Report ' + (i + 1), // or whatever
                    empty: true
                };
                // insert the empty item at the place it should be
                column.value.splice(i, 0, emptyItem);
            } else {
                column.value[i].reportName = 'Report ' + (i + 1);
            }
        }
    }
}
ngOnInit(){
让rawData=this.myService.get();
对于(让rawData的站点地图){
siteMap.value.sort(this.compare);
}
这个.fillEmptyData(rawData);
this.reportRow=rawData;
}
私人比较(a,b){
if(a.reportIdb.reportId)
返回1;
返回0;
}
专用fillEmptyData(dataToFill){
for(让dataToFill列){
如果(!column.value){
column.value=[];
}
for(设i=0;i<3;i++){
如果(!column.value[i]| column.value[i].reportId!==(i+1)){
//column.value[i]不包含预期的reportId
让emptyItem={
报告ID:i+1,
reportName:'报告'+(i+1),//或其他
空的:真的
};
//将空项目插入其应位于的位置
列值拼接(i,0,emptyItem);
}否则{
column.value[i].reportName='Report'+(i+1);
}
}
}
}
然后,您将清除html部分:

<div *ngFor="let siteMap of reportRow; let i = index;" >
   {{ siteMap.key }}
    <div *ngFor="let pMap of siteMap.value; let xi = index;" >
        <tr *ngIf="pMap.yellow === 'Y'">
          <td><span class="yellowcolor"></span> <b>{{pMap.reportName}} Yellow</b></td>
        </tr>
        <tr *ngIf="pMap.red === 'Y'">
          <td><span class="redcolor"></span> <b>{{pMap.reportName}} Red</b></td>
        </tr>
        <tr *ngIf="pMap.empty === true">
          <td><span  class="greencolor"></span><b>{{pMap.reportName}} Green</b></td>
        </tr>
    </div>
</div>

{{siteMap.key}
{{pMap.reportName}}黄色
{{pMap.reportName}}红色
{{pMap.reportName}}绿色
结果如下:

@MizAkita将此评论作为答案发布,因为解决方案有效


假设您能够创建一个已经绘制了报告ID的数组,那么在对
站点地图
进行循环之后,您可以创建另一个
*ngIf

<div *ngFor="let pMap of siteMap.value; let xi = index;"> 
   <div *ngIf="!newArray.includes(pMap.reportId)"> ... </div> 
</div>

...  

如果报告ID发生更改怎么办?此解决方案似乎在ID中迭代。我更喜欢在html forloop中执行此操作,但我可能会被迫在组件中执行此操作。@MizAkita“更改”是什么意思?你是说你多次检索数据?所以你可以用我写的来初始化数组,然后,用一种新的方法来更新数据,而不是用Scratch来构建数据。我很难做到这一点。我已经在对组件中的数据进行排序和格式化,以构建命名对象reportRow,这样我就不需要subscribe方法了。。。我如何使用格式化的ReportRow(其结构请参见原始问题)来代替您的myservice.get()初始调用?@MizAkita如果您掌握了ReportRow的构建方式,那么您可以按照我在一开始时的建议进行操作,这样您就不必对其进行排序/填充。事实上,它不是一个异步调用,这使它变得更容易,请看我编辑的答案。这稍微有效,但有问题。问题是,我的报告名称(列在每行彩色圆圈上)(不一定是上面问题中列出的名称)是唯一的数字。它们不应该被重复。此外,它看起来不像.sort()允许像我在问题中那样的对象数组。我该如何解决这个问题,才能在像我这样的数据结构3D上工作。我收到一个.sort()错误。为什么不在绘图时将绘制的报表ID推送到一个新数组中,然后如果它已经存在于绘制的报表ID数组中,则可以省略它们,使其不再重复。我将如何处理?我可以将id推送到数组中,但我会在组件或html中忽略它们吗?你能创建一个答案吗@NuguLets说你能创建一个已经绘制了报告ID的数组,然后你可以在为siteMap循环后创建另一个
*ngIf
<代码>
此newArray.includes检查是否属于“greenColor”元素?我有点困惑@Nugu@Nugu我想我明白你的意思。让我试一试。