Angular 5 is not rendering the component until click or hover anywhere
Asked Answered
R

4

9

im having this issue which is breaking my head right now and I cant figured out what is the problem. I have a form called device-form, which is called from the dashboard using routing. The device form has inside 4 tabs (angular material), and the second one must show a Highchart component, when you select that tab, the container appears but not the chart.... if you wait, the chart will never show up, but if you click in any place the chart appears, also if you hover some item with mouse, or if you resize the screen!!

Here is one screenshot

App-chart-box.component.html:

<mat-card fxFlex="100%" fxLayout="row">
<mat-card-title></mat-card-title>
<mat-card-content>
    <mat-tab-group class="form-wizard tab-group">
        <mat-tab *ngFor="let chart of charts; let i = index">
            <ng-template mat-tab-label>
                {{ chart.sensorTypeName }}
            </ng-template>
            <div class="tab-content">
                <vr-chart class="card-img-top" [title]="chart.sensorTypeName" [yTitle]="chart.sensorTypeUnit" type="spline" [series]="chart.series"
                    [period]="period" [minThreshold]="minThreshold" [maxThreshold]="maxThreshold"></vr-chart>
            </div>
        </mat-tab>
    </mat-tab-group>
</mat-card-content>
<mat-card-actions>
    <small class="footer">Last updated: {{ dateUpdated }}</small>
</mat-card-actions>

device-form.component.html:

 <mat-tab>
      <ng-template mat-tab-label>
        <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
          <span>Statistics</span>
        </div>
      </ng-template>
      <div fxFlex="100%" class="shipping-address" fxLayout="column">
        <mat-form-field class="select-period">
          <mat-select placeholder="{{ 'DEVICE_FORM.PERIOD' | translate }}" [(ngModel)]="filterPeriodSelected" (change)="loadDeviceChart()">
            <mat-option *ngFor="let period of chartPeriods" [value]="period.value">
              {{ period.label | translate }}
            </mat-option>
          </mat-select>
        </mat-form-field>
        <!-- <div *ngIf="deviceCharts.length == 0" class="alert bg-primary alert-dismissible fade show" role="alert">
          <strong class="ng-tns-c6-44"> {{'MESSAGE.NO_DATA_TO_SHOW' | translate}}</strong>
        </div> -->
        <vr-chart-box *ngIf="deviceCharts" class="fix-width" [charts]="deviceCharts" [period]="filterPeriodSelected"></vr-chart-box>
      </div>
    </mat-tab>

As you see the app-chart-box component is rendered, actually we can always see the footer loaded, always, but the body of the chart dont appear until click or hover o whatever.

another screenshot

Update: Actually Im having the very same issue with a table which is filled with data coming from an API when you change a dropdown up there in the main dashboard page, the table component is always listening to .onCompanyChange.subscribe, read all the data, but the table is not showing until you make click or hover or whatever event... this is the code : Table component:

export class CompanyHistoryComponent implements OnInit {
  @ViewChild('tableInput') tableInput: ElementRef;
  @Input() companyId = 0;
  private rows: Observable<Array<any>>;
  // public rows: any[] = [];

  resultsLength: number;
  dataSource: ListDataSource<any> | null;
  database: ListDatabase<any>;
  tableHover = true;
  tableStriped = true;
  tableCondensed = true;
  tableBordered = true;

  constructor(
    public sensorService: SensorService,
    public dashboardService: DashboardService,
    private cd: ChangeDetectorRef,
  ) {
    // Selected company changed
    this.dashboardService.onCompanyChange.subscribe(
      (id: number) => {
        this.companyId = id;
        this.loadSensorHistory();
        cd.detectChanges();
      });
  }

  public loadSensorHistory() {
    const sDate: Number = moment().subtract(30, 'day').unix()
    const eDate: Number = moment().unix();

    this.sensorService.getSensorDataHistory(this.companyId, sDate, eDate, null, null, 1, 10).subscribe(response => {
      if (response.statusCode !== 200 || !response.data) {
        // this.toastrService.error('MESSAGE.NO_DATA', 'SENSOR_FORM_LIST.TITLE', { positionClass: 'toast-top-right', closeButton: true });
      } else {
        this.rows = response.data.list;
      }
    });
  }
  ngOnInit() {

  }

As you see this time I added detectChanges() without any results :( let me know if you have an idea. This is the HTML of the Table :

<table class="table" [class.table-hover]="tableHover" [class.table-striped]="tableStriped" [class.table-condensed]="tableCondensed"
  [class.table-bordered]="tableBordered">
  <thead>
    <tr>
      <th>Date</th>
      <th>Device</th>
      <th>Sensor</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let row of rows" [class.row-failed]="row.failed > 0">
      <td>{{ row.data_createdDate | date:'MM/dd/yyyy HH:mm:ss a Z' }}</td>
      <td>
        <a href="">{{ row.deviceMAC }}</a>
      </td>
      <td>
        <a href="">{{ row.sensorNumber }} - {{ row.sensorName }}</a>
      </td>
      <td>{{ row.value }}</td>
    </tr>
  </tbody>
</table>
Rubicund answered 27/2, 2018 at 15:33 Comment(3)
Can you post your component TS code for both app-chart-box and device-form?Ulotrichous
You could debug you code and check when and why chart is rendered to make sure it's a right moment or call additional chart.reflow later on.Noll
Check your console. this can occur if a child component is erroringLactoprotein
R
10

You should call ChangeDetectorRef detectChanges()

Racemic answered 27/2, 2018 at 17:10 Comment(5)
Where you suggest to add that?Rubicund
in ngAfterViewInit, ngOnInit. depends on how you get data for charts. If you use service you can call it in the response.Racemic
You can also change the changedetection to push and use immutable data.Racemic
The issue is the same. You call the detectchanges, but the this.loadSensorHistory() which fetches the data is async. So you have to call detectchanges in the response of this.sensorService.getSensorDataHistory or you have to add async/await and wait for it ends.Racemic
I've run into this same problem and detectChanges() fixes the initial load but is now interfering with my mat-select boxes where they are now hanging my browser. Need to find the root cause reallyMorning
P
2

It might be an incorrect pipe operator. I had a similar issue with Angular 11 and mat-table. The rows wouldn't show up until I hovered over them. My issue was that I was using an invalid pipe operator on one of the columns. I was using a decimal pipe on a string column. Once I corrected that it works perfectly.

Pennsylvanian answered 28/10, 2021 at 18:21 Comment(0)
A
1

Add private cd: ChangeDetectorRef in constructor and call this this.cd.detectChanges(); after the specific variable where data is getting updated.

For Example, variable additionalPropertiesForDisplay is used inside ngFor where data is not rendering on hover or click action on screen enter image description here

so calling change detector as mentioned in below image to make data to load when page loads without waiting for hover or click events to occur on screen enter image description here

Abhorrence answered 10/7, 2023 at 4:9 Comment(0)
C
0

I had the same problem, I had set this value for ChangeDetection: ChangeDetectionStrategy.OnPush, replacing it with the default value fixed it for me

Consequence answered 29/8 at 4:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.