0

I'm having a weird interaction between two widely used libraries inside my Angular 4 application: ng-bootstrap (ng-bootstrap) and Highcharts (Highcharts).

I have this metering component containing two child components: data-selection and metering-chart, as so:

<div>
    <data-selection (selectedEntities)="onSelectedData()"></data-selection>
    <button (click)="loadMeteringData()">Load Data</button>
    <metering-chart *ngIf="chartData" [chartData]="chartData"></metering-chart>
</div>

Where data-selection contains the following -stripped- template:

[...]
<form class="form-inline">
    <div class="form-group">
        [...]
        <div class="input-group">
            <input class="form-control" 
                   placeholder="yyyy-mm-dd" 
                   name="dpStart" 
                   [(ngModel)]="startDateModel" 
                   ngbDatepicker 
                   #startDate="ngbDatepicker">
            <div class="input-group-addon" 
                 (click)="startDate.toggle()">
                <i class="fa fa-calendar"></i>
            </div>
            [...]
        </div>
    </div>
</form>
[...]

And the metering-chart component contains:

<chart [options]="options" 
    (load)="createChartObject($event.context)"
    (drilldown)="drilledDown($event)"
    (drillup)="drilledUp($event)" style="width:100%; display: inline-block; "></chart>

The metering component is a router-outlet declared in a Routes file, which is in turn imported by a RoutingModule. This RoutingModule imports SharedModule (where both child components: data-selection and metering-chart are declared and exported), and is imported by the main AppModule.

Since initially metering's chartData is undefined, the metering-chart component is not displayed. During this time, the datepickers work like a charm.

However, it is only when I click the button to load the chart's data and the chart itself, that the datepicker's popup containers become unresponsive.

I have tried to create a plunker where the issue was reproduced, but to no avail... However, here's a gif showing what's going on:

Weird library interaction

As you can see, the model is being updated when the date is typed directly into the input field. However, clicking on any of the dates yield no result whatsoever.

I'm using the following:

Angular v. 4.0.1 angular2-highcharts v. 0.5.5 ng-bootstrap v. 1.0.0-alpha.27

I could provide a ton more information regarding architecture or component interaction, but there's so much of it that, if anything critical should be missing from my question, please tell me and I'll provide it all.

3
  • It's very unlikely that a solution can be suggested here without a plunk or other stackoverflow.com/help/mcve . If you cannot replicate the problem, how can the answerer do this? Commented Jul 10, 2017 at 22:25
  • I'm aware of the difficulty. I was hoping such an interaction could spark some idea on a brighter, broader mind... Believe me I have tried to replicate the issue on a plunker, as I understood perfectly well the ambiguity of my question. Nonetheless, I hoped for someone to shed some light on the matter... After all, Plunker hasn't always been around... Commented Jul 10, 2017 at 22:30
  • 1
    Plunker wasn't around, but MCVE is required by SO rules, and working example seriously increases chances of having someone who will spare some time to debug a problem. Since this isn't Angular or JS theoretical question and Highcharts/Bootstrap/whatever add too many moving parts, this can't be solved by deduction alone (some questions can but not this one). Commented Jul 10, 2017 at 23:08

1 Answer 1

2

Taken from Alios' answer which links to ng-boostrap's GitHub issue page:

The problem does not reside in a faulty interaction between libraries, but rather in a wrong creation of the chart element. Apparently it was being created inside an Angular Zone, thus triggering change detection on every event handler.

The solution was to remove the chart creation & update event bindings from the metering-chart component template, leaving it like so:

<div id="chart-container"></div>

And leaving the the chart creation, data update, and drilldown/up events to be handled outside the angular zone:

this.zone.runOutsideAngular(() => {
    // Create or Update the chart
})

Furthermore, all the event bindings defined in the previous <chart> element have to be redefined inside the component's logic and options object.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.