Search code examples
angulartypescripthighchartsngforangular-ng-if

Highcharts creating multiple charts. Want to make changes to only the first


Editing an Angular stack and having trouble when multiple charts are created and only one needs customized.

Code below creates a chart with all plots stacked, and then creates a single chart for each plot stacked on the page to the right in a virtual scroll. I'm trying to edit the ngIf to only run my subtitle function when the chart id = rawTraceHighChart0(topmost chart), which is set with i if its a singletracedataset.

I have been trying different methods for this all day and looking everywhere and cannot figure this out so I'm begging for any help. I have tried to add an id condition to the ngIf with a new #subtitle template, tried setting it manually and searching high and low for an answer. The #singlechart template works great and my subtitle function isn't causing the issues, but I can't find a unique identifier/method to create an addition to the ngIf that will only apply to the first/top/rawTraceHighChart0 chart.

HTML:

<div *ngIf="displayDataSet && datasets; else loading">
    <div *ngIf="displayDataSet?.data?.length > 0; else noData">
        <div *ngIf="!anomExists" class="alert alert-warning">
            <i class="fa fa-exclamation-circle" aria-hidden="true"></i> Raw Trace not found for Run ID: {{this.displayStateService.appState.current.context['RUN_ID']}}
        </div>
        <div style="height: 100vh; overflow-y: auto;" *ngIf="Config.config.multiChart == 'true'; else singleChart">
            <virtual-scroll class="virtual-scroll" [childHeight]="300" [items]="datasets" (update)="viewPortItems = $event" (change)="indices = $event">
                <div *ngFor="let dataset of viewPortItems; let i = index;">
                    <div *ngFor="let name of dataset?.infoNames; let j = index;">
                        <h6 style="text-align: center;">{{ datasets[GetAdjustedIndex(i)]?.infoNames[j] }}:
                            <strong>{{ datasets[GetAdjustedIndex(i)]?.infoData[j] }}</strong>
                        </h6>
                    </div>
                    <app-highchart-platform *ngIf="SingleTraceDataSet" [id]="'rawTraceHighChart'+ GetAdjustedIndex(i)" [data]="SingleTraceDataSet[GetAdjustedIndex(i)]" [type]="'line'" [overrideConfig]="overrideConfigRawTrace" [title]="'Raw Trace'">
                        {{subtitle()}}
                    </app-highchart-platform>
                    <hr>
                </div>
            </virtual-scroll>
        </div>

        <ng-template #singleChart>

            <app-highchart-platform *ngIf="RawTraceDataSet" [id]="'rawTraceVPopulationHighChart'" [data]="RawTraceDataSet" [type]="'line'" [overrideConfig]="overrideConfigRawTrace" [title]="'Raw Trace vs. Population'">
                {{subtitle()}}
            </app-highchart-platform>

        </ng-template>

    </div>

    <ng-template #noData>
        No data available.
    </ng-template>

</div>

<ng-template #loading>
    <i class="fa fa-spinner fa-spin"></i> Loading data...
</ng-template>

Subtitle Function:

public subtitle() {
    const context = this.displayStateService.appState.current.context;
    this.overrideConfigRawTrace.subtitle = {
      useHTML: true,
      text: '<div align="center" style="font-size:80%">' + '<b>FAB: </b>' + context['FAB'] + '<b>, DESIGN ID: </b>'
       + context['DESIGN_ID'] + '<b>, STEP: </b>' + context['TRAVELER_STEP'] + '<br>' + '<b>TOOL: </b>'
      + context['TOOL_NAME'] + '<b>, PROCESS: </b>' + context['GERM_PROCESS'] + '<b>, RECIPE: </b>' + context['RECIPE_NAME']
       + '<br>' + '<b>SENSOR: </b>' + context['SENSOR_NAME'] + '<b>, RUN ID: </b>' + context['RUN_ID'] + '</div>',
    };
  }
  }

Solution

  • Actually, the problem is in *ngIf, suppose if you are using *ngIf for div then that div is only rendered on the DOM when the condition is true, that's why your code for highchart is not rendering on the browser. and highchart is searching ID element on DOM which is not present on DOM.

    If This is not then You can create Dynamic Unique Ids and store into the array and then use as per the index value : e.g.

    const dynamicIds = []; 
        const NUMBER_OF_RACES =5;
        for (let i = 1; i < NUMBER_OF_RACES; i += 1) {
           dynamicIds.push(Math.random().toString(36).substr(2, 5));
        }